From: Kyrill Tkachov <kyrylo.tkachov@arm.com>
To: Segher Boessenkool <segher@kernel.crashing.org>,
"gcc-patches@gcc.gnu.org" <gcc-patches@gcc.gnu.org>
Cc: "dje.gcc@gmail.com" <dje.gcc@gmail.com>
Subject: Re: [PATCH 2/6] combine: If recog fails, try again with zero_ext{ract,end} simplified
Date: Tue, 12 May 2015 08:25:00 -0000 [thread overview]
Message-ID: <5551B7C2.9050502@arm.com> (raw)
In-Reply-To: <00854266aef1cbae6d3620f78122e6131c37b73c.1431268135.git.segher@kernel.crashing.org>
Hi Segher,
On 10/05/15 17:13, Segher Boessenkool wrote:
> Combine has its own ideas of what is "canonical" RTL, forcing all
> backends to have special patterns in their machine description for the
> "more simplified" patterns combine often creates, even though the
> backend already has patterns for a more general form. Backends that
> do not implement those patterns get less well optimised code.
>
> This patch lifts that burden for two cases: combine often converts
> an AND (with, say, 0xff) to a ZERO_EXTEND of a SUBREG; and an LSHIFTRT
> followed by an AND to a ZERO_EXTRACT. This is perfectly helpful for
> e.g. MEMs, but not nice if you have instructions to do more generic
> masking (like PowerPC rlwinm, and similar on some other archs).
>
> With this patch, if recog_for_combine fails, and there are any
> ZERO_EXT* in the pattern to be matched, it tries again with those
> expressed as AND etc. If that also fails it rolls back the changes,
> because it might still match after e.g. splitting, and we want to
> try the ZERO_EXT* for that as well.
>
> Tested on powerpc-linux, before and after removing many patterns
> from the machine description, and checked that the only changes in
> the bootstrapped compiler are new and removed functions.
Does this patch means we can remove any patterns in
the backend that look like:
- [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
- (zero_extract:SI (match_operand:SI 1 "gpc_reg_operand" "r")
- (match_operand:SI 2 "const_int_operand" "i")
- (match_operand:SI 3 "const_int_operand" "i")))]
as long as we have an equivalent and-with-mask pattern?
Thanks,
Kyrill
>
> I'll also test on x86_64-linux before committing.
>
>
> Segher
>
>
> 2015-05-10 Segher Boessenkool <segher@kernel.crashing.org>
>
> * combine.c (recog_for_combine_1): New function, factored out
> from recog_for_combine.
> (change_zero_ext): New function.
> (recog_for_combine): If recog fails, try again with the pattern
> modified by change_zero_ext; if that still fails, restore the
> pattern.
>
> ---
> gcc/combine.c | 120 +++++++++++++++++++++++++++++++++++++++++++++++++++-------
> 1 file changed, 107 insertions(+), 13 deletions(-)
>
> diff --git a/gcc/combine.c b/gcc/combine.c
> index 1e4d65e..896d9d2 100644
> --- a/gcc/combine.c
> +++ b/gcc/combine.c
> @@ -10849,21 +10849,11 @@ simplify_shift_const (rtx x, enum rtx_code code, machine_mode result_mode,
> }
>
> \f
> -/* Like recog, but we receive the address of a pointer to a new pattern.
> - We try to match the rtx that the pointer points to.
> - If that fails, we may try to modify or replace the pattern,
> - storing the replacement into the same pointer object.
> -
> - Modifications include deletion or addition of CLOBBERs.
> -
> - PNOTES is a pointer to a location where any REG_UNUSED notes added for
> - the CLOBBERs are placed.
> -
> - The value is the final insn code from the pattern ultimately matched,
> - or -1. */
> +/* A subroutine of recog_for_combine. See there for arguments and
> + return value. */
>
> static int
> -recog_for_combine (rtx *pnewpat, rtx_insn *insn, rtx *pnotes)
> +recog_for_combine_1 (rtx *pnewpat, rtx_insn *insn, rtx *pnotes)
> {
> rtx pat = *pnewpat;
> rtx pat_without_clobbers;
> @@ -11010,6 +11000,110 @@ recog_for_combine (rtx *pnewpat, rtx_insn *insn, rtx *pnotes)
>
> return insn_code_number;
> }
> +
> +/* Change every ZERO_EXTRACT and ZERO_EXTEND of a SUBREG that can be
> + expressed as an AND and maybe an LSHIFTRT, to that formulation.
> + Return whether anything was so changed. */
> +
> +static bool
> +change_zero_ext (rtx *src)
> +{
> + bool changed = false;
> +
> + subrtx_ptr_iterator::array_type array;
> + FOR_EACH_SUBRTX_PTR (iter, array, src, NONCONST)
> + {
> + rtx x = **iter;
> + machine_mode mode = GET_MODE (x);
> + int size;
> +
> + if (GET_CODE (x) == ZERO_EXTRACT
> + && CONST_INT_P (XEXP (x, 1))
> + && CONST_INT_P (XEXP (x, 2))
> + && GET_MODE (XEXP (x, 0)) == mode)
> + {
> + size = INTVAL (XEXP (x, 1));
> +
> + int start = INTVAL (XEXP (x, 2));
> + if (BITS_BIG_ENDIAN)
> + start = GET_MODE_PRECISION (mode) - size - start;
> +
> + x = gen_rtx_LSHIFTRT (mode, XEXP (x, 0), GEN_INT (start));
> + }
> + else if (GET_CODE (x) == ZERO_EXTEND
> + && GET_CODE (XEXP (x, 0)) == SUBREG
> + && GET_MODE (SUBREG_REG (XEXP (x, 0))) == mode
> + && subreg_lowpart_p (XEXP (x, 0)))
> + {
> + size = GET_MODE_PRECISION (GET_MODE (XEXP (x, 0)));
> + x = SUBREG_REG (XEXP (x, 0));
> + }
> + else
> + continue;
> +
> + unsigned HOST_WIDE_INT mask = 1;
> + mask <<= size;
> + mask--;
> +
> + x = gen_rtx_AND (mode, x, GEN_INT (mask));
> +
> + SUBST (**iter, x);
> + changed = true;
> + }
> +
> + return changed;
> +}
> +
> +/* Like recog, but we receive the address of a pointer to a new pattern.
> + We try to match the rtx that the pointer points to.
> + If that fails, we may try to modify or replace the pattern,
> + storing the replacement into the same pointer object.
> +
> + Modifications include deletion or addition of CLOBBERs. If the
> + instruction will still not match, we change ZERO_EXTEND and ZERO_EXTRACT
> + to the equivalent AND and perhaps LSHIFTRT patterns, and try with that
> + (and undo if that fails).
> +
> + PNOTES is a pointer to a location where any REG_UNUSED notes added for
> + the CLOBBERs are placed.
> +
> + The value is the final insn code from the pattern ultimately matched,
> + or -1. */
> +
> +static int
> +recog_for_combine (rtx *pnewpat, rtx_insn *insn, rtx *pnotes)
> +{
> + rtx pat = PATTERN (insn);
> + int insn_code_number = recog_for_combine_1 (pnewpat, insn, pnotes);
> + if (insn_code_number >= 0 || check_asm_operands (pat))
> + return insn_code_number;
> +
> + void *marker = get_undo_marker ();
> + bool changed = false;
> +
> + if (GET_CODE (pat) == SET)
> + changed = change_zero_ext (&SET_SRC (pat));
> + else if (GET_CODE (pat) == PARALLEL)
> + {
> + int i;
> + for (i = 0; i < XVECLEN (pat, 0); i++)
> + {
> + rtx set = XVECEXP (pat, 0, i);
> + if (GET_CODE (set) == SET)
> + changed |= change_zero_ext (&SET_SRC (set));
> + }
> + }
> +
> + if (changed)
> + {
> + insn_code_number = recog_for_combine_1 (pnewpat, insn, pnotes);
> +
> + if (insn_code_number < 0)
> + undo_to_marker (marker);
> + }
> +
> + return insn_code_number;
> +}
> \f
> /* Like gen_lowpart_general but for use by combine. In combine it
> is not possible to create any new pseudoregs. However, it is
next prev parent reply other threads:[~2015-05-12 8:20 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-05-10 16:14 [PATCH 0/6] Getting rid of some zero_ext* patterns Segher Boessenkool
2015-05-10 16:14 ` [PATCH 1/6] combine: undo_to_marker Segher Boessenkool
2015-05-11 4:10 ` Jeff Law
2015-05-10 16:15 ` [PATCH 3/6] rs6000: Don't use zero_extract in the bswap:HI splitter Segher Boessenkool
2015-05-11 15:32 ` David Edelsohn
2015-05-10 16:15 ` [PATCH 2/6] combine: If recog fails, try again with zero_ext{ract,end} simplified Segher Boessenkool
2015-05-11 4:15 ` Jeff Law
2015-05-11 6:18 ` Segher Boessenkool
2015-05-12 8:25 ` Kyrill Tkachov [this message]
2015-05-12 11:16 ` Segher Boessenkool
2015-05-10 16:16 ` [PATCH 6/6] rs6000: Clean up the various rlwinm patterns Segher Boessenkool
2015-05-10 18:02 ` Maciej W. Rozycki
2015-05-10 19:45 ` Segher Boessenkool
2015-05-11 18:17 ` Maciej W. Rozycki
2015-05-11 15:31 ` David Edelsohn
2015-05-10 16:16 ` [PATCH 4/6] rs6000: Delete some now-superfluous zero_ext{end,ract} patterns Segher Boessenkool
2015-05-11 15:29 ` David Edelsohn
2015-05-10 16:16 ` [PATCH 5/6] rs6000: Don't use gen_rlwinm Segher Boessenkool
2015-05-11 15:30 ` David Edelsohn
2015-05-12 14:01 ` [PATCH 0/6] Getting rid of some zero_ext* patterns Segher Boessenkool
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=5551B7C2.9050502@arm.com \
--to=kyrylo.tkachov@arm.com \
--cc=dje.gcc@gmail.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=segher@kernel.crashing.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).