& ~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 (partial_subreg_p (op)
+ && GET_CODE (XEXP (op, 0)) == NOT
+ && GET_MODE (XEXP (op, 0)) == mode
+ && subreg_lowpart_p (op)
+ && HWI_COMPUTABLE_MODE_P (mode)
+ && is_a <scalar_int_mode> (GET_MODE (op), &op_mode)
+ && (nonzero_bits (XEXP (XEXP (op, 0), 0), mode)
+ & ~GET_MODE_MASK (op_mode)) == 0)
+ {
+ unsigned HOST_WIDE_INT mask = GET_MODE_MASK (op_mode);
+ 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
--- /dev/null
+/* { 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" } } */