This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Optimize bfi by remove redundant zero_extend
- From: Renlin Li <renlin dot li at arm dot com>
- To: "gcc-patches at gcc dot gnu dot org" <gcc-patches at gcc dot gnu dot org>
- Cc: marcus Shawcroft <Marcus dot Shawcroft at arm dot com>, ramana Radhakrishnan <ramana dot radhakrishnan at arm dot com>, Richard Earnshaw <Richard dot Earnshaw at arm dot com>
- Date: Fri, 13 Feb 2015 16:26:37 +0000
- Subject: [PATCH] Optimize bfi by remove redundant zero_extend
- Authentication-results: sourceware.org; auth=none
Hi all,
The following rtx pattern will be transformed into the second one,
which makes the compiler unable to remove the redundant zero_extend
operation.
(set (zero_extract:SI (reg/i:SI 0 x0)
(const_int 8 [0x8])
(const_int 0 [0]))
(and:SI (reg:SI 1 x1 [ y ])
(const_int 255 [0xff])))
------------------->>>>>>>>>>>>>>>>
(set (zero_extract:SI (reg/i:SI 0 x0)
(const_int 8 [0x8])
(const_int 0 [0]))
(zero_extend:SI (reg:QI 1 x1 [ y ])))
This patch add the code to handle the second case as well.
for example, for the following short code excerpt
int f5(int x, int y)
{
return (x & ~0xff) | (y & 0xff);
}
original code-gen is:
uxtb w1, w1
bfi w0, w1, 0, 8
ret
new code-gen is:
bfi w0, w1, 0, 8
ret
x86-64 bootstraps Okay, aarch64-none-elf regression test Okay.
Okay for trunk?
Regards,
Renlin Li
gcc/ChangeLog:
2015-02-13 Renlin Li <renlin.li@arm.com>
* combine.c (make_field_assignment): Add code to remove redundant
ZERO_EXTEND operation.
diff --git a/gcc/combine.c b/gcc/combine.c
index f779117..759e07c 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -9311,6 +9311,31 @@ make_field_assignment (rtx x)
}
}
+ /* If DEST is already a field assignment, i.e. ZERO_EXTRACT, and the
+ SRC is an ZERO_EXTEND with all bits of that field set, then we can discard
+ the ZERO_EXTEND. */
+ if (GET_CODE (dest) == ZERO_EXTRACT
+ && CONST_INT_P (XEXP (dest, 1))
+ && CONST_INT_P (XEXP (dest, 2))
+ && GET_CODE (src) == ZERO_EXTEND
+ && REG_P (XEXP (src, 0)))
+ {
+ unsigned int regno = REGNO (XEXP (src, 0));
+ unsigned int inner_size = GET_MODE_BITSIZE (GET_MODE (XEXP (src, 0)));
+ mode = GET_MODE (src);
+
+ HOST_WIDE_INT width = INTVAL (XEXP (dest, 1));
+ HOST_WIDE_INT lsb = INTVAL (XEXP (dest, 2));
+ /* Complete overlap. We can remove the source ZERO_EXTEND. */
+ if (width == inner_size
+ && (regno < FIRST_PSEUDO_REGISTER)
+ && HARD_REGNO_MODE_OK (regno, mode))
+ {
+ rtx reg = gen_rtx_REG (mode, regno);
+ return gen_rtx_SET (VOIDmode, dest, reg);
+ }
+ }
+
/* The other case we handle is assignments into a constant-position
field. They look like (ior/xor (and DEST C1) OTHER). If C1 represents
a mask that has all one bits except for a group of zero bits and