mirror of
https://github.com/gcc-mirror/gcc.git
synced 2024-11-21 13:40:47 +00:00
[PATCH v2] RISC-V: zero_extend(not) -> xor optimization [PR112398]
This patch adds optimization of the following patterns: (zero_extend:M (subreg:N (not:O==M (X:Q==M)))) -> (xor:M (zero_extend:M (subreg:N (X:M)), mask)) ... where the mask is GET_MODE_MASK (N). For the cases when X:M doesn't have any non-zero bits outside of mode N, (zero_extend:M (subreg:N (X:M)) could be simplified to just (X:M) and whole optimization will be: (zero_extend:M (subreg:N (not:M (X:M)))) -> (xor:M (X:M, mask)) Patch targets to handle code patterns like: not a0,a0 andi a0,a0,0xff to be optimized to: xori a0,a0,255 Change was locally tested for x86_64 and AArch64 (as most common) and for RV-64 and MIPS-32 targets (as having an effect from this optimization): no regressions for all cases. PR rtl-optimization/112398 gcc/ChangeLog: * simplify-rtx.cc (simplify_context::simplify_unary_operation_1): Simplify ZERO_EXTEND (SUBREG (NOT X)) to XOR (X, GET_MODE_MASK(SUBREG)) when X doesn't have any non-zero bits outside of SUBREG mode. gcc/testsuite/ChangeLog: * gcc.target/riscv/pr112398.c: New test. Signed-off-by: Alexey Merzlyakov <alexey.merzlyakov@samsung.com>
This commit is contained in:
parent
a91d5c27cd
commit
69bd93c167
@ -1842,6 +1842,28 @@ simplify_context::simplify_unary_operation_1 (rtx_code code, machine_mode mode,
|
||||
& ~GET_MODE_MASK (op_mode)) == 0)
|
||||
return SUBREG_REG (op);
|
||||
|
||||
/* Trying to optimize:
|
||||
(zero_extend:M (subreg:N (not:M (X:M)))) ->
|
||||
(xor:M (zero_extend:M (subreg:N (X:M)), mask))
|
||||
where the mask is GET_MODE_MASK (N).
|
||||
For the cases when X:M doesn't have any non-zero bits
|
||||
outside of mode N, (zero_extend:M (subreg:N (X:M))
|
||||
will be simplified to just (X:M)
|
||||
and whole optimization will be -> (xor:M (X:M, mask)). */
|
||||
if (SUBREG_P (op)
|
||||
&& GET_CODE (XEXP (op, 0)) == NOT
|
||||
&& GET_MODE (XEXP (op, 0)) == mode
|
||||
&& subreg_lowpart_p (op)
|
||||
&& GET_MODE_SIZE (GET_MODE (op)).is_constant ()
|
||||
&& (nonzero_bits (XEXP (XEXP (op, 0), 0), mode)
|
||||
& ~GET_MODE_MASK (mode)) == 0)
|
||||
{
|
||||
const uint64_t mask = GET_MODE_MASK (GET_MODE (op));
|
||||
return simplify_gen_binary (XOR, mode,
|
||||
XEXP (XEXP (op, 0), 0),
|
||||
gen_int_mode (mask, mode));
|
||||
}
|
||||
|
||||
#if defined(POINTERS_EXTEND_UNSIGNED)
|
||||
/* As we do not know which address space the pointer is referring to,
|
||||
we can do this only if the target does not support different pointer
|
||||
|
14
gcc/testsuite/gcc.target/riscv/pr112398.c
Normal file
14
gcc/testsuite/gcc.target/riscv/pr112398.c
Normal file
@ -0,0 +1,14 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-march=rv64gc -mabi=lp64d" } */
|
||||
/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
uint8_t neg_u8 (const uint8_t src)
|
||||
{
|
||||
return ~src;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-assembler-times "xori\t" 1 } } */
|
||||
/* { dg-final { scan-assembler-not "not\t" } } */
|
||||
/* { dg-final { scan-assembler-not "andi\t" } } */
|
Loading…
Reference in New Issue
Block a user