https://gcc.gnu.org/g:10d76b7f1e5b63ad6d2b92940c39007913ced037
commit r15-5185-g10d76b7f1e5b63ad6d2b92940c39007913ced037 Author: Jeff Law <j...@ventanamicro.com> Date: Tue Nov 12 17:12:49 2024 -0700 Reapply "[PATCH v2] RISC-V: zero_extend(not) -> xor optimization [PR112398]" This reverts commit de3b277247ce98d189f121155b75f490725a42f6. Diff: --- gcc/simplify-rtx.cc | 22 ++++++++++++++++++++++ gcc/testsuite/gcc.target/riscv/pr112398.c | 14 ++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc index 893c5f6e1ae0..d05efac20dc8 100644 --- a/gcc/simplify-rtx.cc +++ b/gcc/simplify-rtx.cc @@ -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 diff --git a/gcc/testsuite/gcc.target/riscv/pr112398.c b/gcc/testsuite/gcc.target/riscv/pr112398.c new file mode 100644 index 000000000000..624a665b76c9 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/pr112398.c @@ -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" } } */