diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/simplify-rtx.cc | 50 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/aarch64/simd/bic_orn_1.c | 17 |
2 files changed, 67 insertions, 0 deletions
diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc index d9aa049..7c4d8e6 100644 --- a/gcc/simplify-rtx.cc +++ b/gcc/simplify-rtx.cc @@ -3032,6 +3032,44 @@ match_plus_neg_pattern (rtx op0, rtx op1, machine_mode mode) return false; } +/* Check if OP matches the pattern of (subreg (not X)) and the subreg is + non-paradoxical. */ + +static bool +non_paradoxical_subreg_not_p (rtx op) +{ + return GET_CODE (op) == SUBREG + && !paradoxical_subreg_p (op) + && GET_CODE (SUBREG_REG (op)) == NOT; +} + +/* Convert (binop (subreg (not X)) Y) into (binop (not (subreg X)) Y), or + (binop X (subreg (not Y))) into (binop X (not (subreg Y))) to expose + opportunities to combine another binary logical operation with NOT. */ + +static rtx +simplify_with_subreg_not (rtx_code binop, machine_mode mode, rtx op0, rtx op1) +{ + rtx opn = NULL_RTX; + if (non_paradoxical_subreg_not_p (op0)) + opn = op0; + else if (non_paradoxical_subreg_not_p (op1)) + opn = op1; + + if (opn == NULL_RTX) + return NULL_RTX; + + rtx new_subreg = simplify_gen_subreg (mode, + XEXP (SUBREG_REG (opn), 0), + GET_MODE (SUBREG_REG (opn)), + SUBREG_BYTE (opn)); + rtx new_not = simplify_gen_unary (NOT, mode, new_subreg, mode); + if (opn == op0) + return simplify_gen_binary (binop, mode, new_not, op1); + else + return simplify_gen_binary (binop, mode, op0, new_not); +} + /* Subroutine of simplify_binary_operation. Simplify a binary operation CODE with result mode MODE, operating on OP0 and OP1. If OP0 and/or OP1 are constant pool references, TRUEOP0 and TRUEOP1 represent the @@ -3749,6 +3787,10 @@ simplify_context::simplify_binary_operation_1 (rtx_code code, && rtx_equal_p (XEXP (XEXP (op0, 0), 0), op1)) return simplify_gen_binary (IOR, mode, XEXP (op0, 1), op1); + tem = simplify_with_subreg_not (code, mode, op0, op1); + if (tem) + return tem; + tem = simplify_byte_swapping_operation (code, mode, op0, op1); if (tem) return tem; @@ -4017,6 +4059,10 @@ simplify_context::simplify_binary_operation_1 (rtx_code code, && rtx_equal_p (XEXP (XEXP (op0, 0), 0), op1)) return simplify_gen_binary (IOR, mode, XEXP (op0, 1), op1); + tem = simplify_with_subreg_not (code, mode, op0, op1); + if (tem) + return tem; + tem = simplify_byte_swapping_operation (code, mode, op0, op1); if (tem) return tem; @@ -4285,6 +4331,10 @@ simplify_context::simplify_binary_operation_1 (rtx_code code, return simplify_gen_binary (LSHIFTRT, mode, XEXP (op0, 0), XEXP (op0, 1)); } + tem = simplify_with_subreg_not (code, mode, op0, op1); + if (tem) + return tem; + tem = simplify_byte_swapping_operation (code, mode, op0, op1); if (tem) return tem; diff --git a/gcc/testsuite/gcc.target/aarch64/simd/bic_orn_1.c b/gcc/testsuite/gcc.target/aarch64/simd/bic_orn_1.c new file mode 100644 index 0000000..1c66f21 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/simd/bic_orn_1.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +#include <arm_neon.h> + +int64x2_t bic_16b (int32x4_t a, int32x4_t b) { + return vandq_s64 (vreinterpretq_s64_s32 (vmvnq_s32 (a)), + vreinterpretq_s64_s32 (b)); +} + +int16x4_t orn_8b (int32x2_t a, int32x2_t b) { + return vorr_s16 (vreinterpret_s16_s32 (a), + vreinterpret_s16_s32 (vmvn_s32 (b))); +} + +/* { dg-final { scan-assembler {\tbic\tv[0-9]+\.16b} } } */ +/* { dg-final { scan-assembler {\torn\tv[0-9]+\.8b} } } */ |