[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:
Alexey Merzlyakov 2024-11-06 14:39:30 -07:00 committed by Jeff Law
parent a91d5c27cd
commit 69bd93c167
2 changed files with 36 additions and 0 deletions

View File

@ -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

View 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" } } */