https://gcc.gnu.org/g:8762bb1b004c442b8dbb22a6d9eb0b7da4a3e59f
commit r15-4886-g8762bb1b004c442b8dbb22a6d9eb0b7da4a3e59f Author: Kyrylo Tkachov <ktkac...@nvidia.com> Date: Mon Nov 4 14:04:59 2024 +0100 Revert "PR 117048: simplify-rtx: Simplify (X << C1) [+,^] (X >> C2) into ROTATE" This reverts commit de2bc6a7367aca2eecc925ebb64cfb86998d89f3. Diff: --- gcc/simplify-rtx.cc | 204 +++++++++++++--------------------------------------- 1 file changed, 48 insertions(+), 156 deletions(-) diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc index 751c908113ef..ce8d3879270d 100644 --- a/gcc/simplify-rtx.cc +++ b/gcc/simplify-rtx.cc @@ -2820,104 +2820,6 @@ reverse_rotate_by_imm_p (machine_mode mode, unsigned int left, rtx op1) return false; } -/* Analyse argument X to see if it represents an (ASHIFT X Y) operation - and return the expression to be shifted in SHIFT_OPND and the shift amount - in SHIFT_AMNT. This is primarily used to group handling of ASHIFT (X, CST) - and (PLUS (X, X)) in one place. If the expression is not equivalent to an - ASHIFT then return FALSE and set SHIFT_OPND and SHIFT_AMNT to NULL. */ - -static bool -extract_ashift_operands_p (rtx x, rtx *shift_opnd, rtx *shift_amnt) -{ - if (GET_CODE (x) == ASHIFT) - { - *shift_opnd = XEXP (x, 0); - *shift_amnt = XEXP (x, 1); - return true; - } - if (GET_CODE (x) == PLUS && rtx_equal_p (XEXP (x, 0), XEXP (x, 1))) - { - *shift_opnd = XEXP (x, 0); - *shift_amnt = CONST1_RTX (GET_MODE (x)); - return true; - } - *shift_opnd = NULL_RTX; - *shift_amnt = NULL_RTX; - return false; -} - -/* OP0 and OP1 are combined under an operation of mode MODE that can - potentially result in a ROTATE expression. Analyze the OP0 and OP1 - and return the resulting ROTATE expression if so. Return NULL otherwise. - This is used in detecting the patterns (X << C1) [+,|,^] (X >> C2) where - C1 + C2 == GET_MODE_UNIT_PRECISION (mode). - (X << C1) and (C >> C2) would be OP0 and OP1. */ - -static rtx -simplify_rotate_op (rtx op0, rtx op1, machine_mode mode) -{ - /* Convert (ior (ashift A CX) (lshiftrt A CY)) where CX+CY equals the - mode size to (rotate A CX). */ - - rtx opleft = simplify_rtx (op0); - rtx opright = simplify_rtx (op1); - rtx ashift_opnd, ashift_amnt; - /* In some cases the ASHIFT is not a direct ASHIFT. Look deeper and extract - the relevant operands here. */ - bool ashift_op_p - = extract_ashift_operands_p (op1, &ashift_opnd, &ashift_amnt); - - if (ashift_op_p - || GET_CODE (op1) == SUBREG) - { - opleft = op1; - opright = op0; - } - else - { - opright = op1; - opleft = op0; - ashift_op_p - = extract_ashift_operands_p (opleft, &ashift_opnd, &ashift_amnt); - } - - if (ashift_op_p && GET_CODE (opright) == LSHIFTRT - && rtx_equal_p (ashift_opnd, XEXP (opright, 0))) - { - rtx leftcst = unwrap_const_vec_duplicate (ashift_amnt); - rtx rightcst = unwrap_const_vec_duplicate (XEXP (opright, 1)); - - if (CONST_INT_P (leftcst) && CONST_INT_P (rightcst) - && (INTVAL (leftcst) + INTVAL (rightcst) - == GET_MODE_UNIT_PRECISION (mode))) - return gen_rtx_ROTATE (mode, XEXP (opright, 0), ashift_amnt); - } - - /* Same, but for ashift that has been "simplified" to a wider mode - by simplify_shift_const. */ - scalar_int_mode int_mode, inner_mode; - - if (GET_CODE (opleft) == SUBREG - && is_a <scalar_int_mode> (mode, &int_mode) - && is_a <scalar_int_mode> (GET_MODE (SUBREG_REG (opleft)), - &inner_mode) - && GET_CODE (SUBREG_REG (opleft)) == ASHIFT - && GET_CODE (opright) == LSHIFTRT - && GET_CODE (XEXP (opright, 0)) == SUBREG - && known_eq (SUBREG_BYTE (opleft), SUBREG_BYTE (XEXP (opright, 0))) - && GET_MODE_SIZE (int_mode) < GET_MODE_SIZE (inner_mode) - && rtx_equal_p (XEXP (SUBREG_REG (opleft), 0), - SUBREG_REG (XEXP (opright, 0))) - && CONST_INT_P (XEXP (SUBREG_REG (opleft), 1)) - && CONST_INT_P (XEXP (opright, 1)) - && (INTVAL (XEXP (SUBREG_REG (opleft), 1)) - + INTVAL (XEXP (opright, 1)) - == GET_MODE_PRECISION (int_mode))) - return gen_rtx_ROTATE (int_mode, XEXP (opright, 0), - XEXP (SUBREG_REG (opleft), 1)); - return NULL_RTX; -} - /* 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 @@ -2929,7 +2831,7 @@ simplify_context::simplify_binary_operation_1 (rtx_code code, rtx op0, rtx op1, rtx trueop0, rtx trueop1) { - rtx tem, reversed, elt0, elt1; + rtx tem, reversed, opleft, opright, elt0, elt1; HOST_WIDE_INT val; scalar_int_mode int_mode, inner_mode; poly_int64 offset; @@ -3128,11 +3030,6 @@ simplify_context::simplify_binary_operation_1 (rtx_code code, return simplify_gen_unary (NEG, mode, reversed, mode); - /* Convert (plus (ashift A CX) (lshiftrt A CY)) where CX+CY equals the - mode size to (rotate A CX). */ - if ((tem = simplify_rotate_op (op0, op1, mode))) - return tem; - /* If one of the operands is a PLUS or a MINUS, see if we can simplify this by the associative law. Don't use the associative law for floating point. @@ -3565,10 +3462,53 @@ simplify_context::simplify_binary_operation_1 (rtx_code code, return op1; /* Convert (ior (ashift A CX) (lshiftrt A CY)) where CX+CY equals the - mode size to (rotate A CX). */ - tem = simplify_rotate_op (op0, op1, mode); - if (tem) - return tem; + mode size to (rotate A CX). */ + + if (GET_CODE (op1) == ASHIFT + || GET_CODE (op1) == SUBREG) + { + opleft = op1; + opright = op0; + } + else + { + opright = op1; + opleft = op0; + } + + if (GET_CODE (opleft) == ASHIFT && GET_CODE (opright) == LSHIFTRT + && rtx_equal_p (XEXP (opleft, 0), XEXP (opright, 0))) + { + rtx leftcst = unwrap_const_vec_duplicate (XEXP (opleft, 1)); + rtx rightcst = unwrap_const_vec_duplicate (XEXP (opright, 1)); + + if (CONST_INT_P (leftcst) && CONST_INT_P (rightcst) + && (INTVAL (leftcst) + INTVAL (rightcst) + == GET_MODE_UNIT_PRECISION (mode))) + return gen_rtx_ROTATE (mode, XEXP (opright, 0), XEXP (opleft, 1)); + } + + /* Same, but for ashift that has been "simplified" to a wider mode + by simplify_shift_const. */ + + if (GET_CODE (opleft) == SUBREG + && is_a <scalar_int_mode> (mode, &int_mode) + && is_a <scalar_int_mode> (GET_MODE (SUBREG_REG (opleft)), + &inner_mode) + && GET_CODE (SUBREG_REG (opleft)) == ASHIFT + && GET_CODE (opright) == LSHIFTRT + && GET_CODE (XEXP (opright, 0)) == SUBREG + && known_eq (SUBREG_BYTE (opleft), SUBREG_BYTE (XEXP (opright, 0))) + && GET_MODE_SIZE (int_mode) < GET_MODE_SIZE (inner_mode) + && rtx_equal_p (XEXP (SUBREG_REG (opleft), 0), + SUBREG_REG (XEXP (opright, 0))) + && CONST_INT_P (XEXP (SUBREG_REG (opleft), 1)) + && CONST_INT_P (XEXP (opright, 1)) + && (INTVAL (XEXP (SUBREG_REG (opleft), 1)) + + INTVAL (XEXP (opright, 1)) + == GET_MODE_PRECISION (int_mode))) + return gen_rtx_ROTATE (int_mode, XEXP (opright, 0), + XEXP (SUBREG_REG (opleft), 1)); /* If OP0 is (ashiftrt (plus ...) C), it might actually be a (sign_extend (plus ...)). Then check if OP1 is a CONST_INT and @@ -3898,12 +3838,6 @@ simplify_context::simplify_binary_operation_1 (rtx_code code, return tem; } - /* Convert (xor (ashift A CX) (lshiftrt A CY)) where CX+CY equals the - mode size to (rotate A CX). */ - tem = simplify_rotate_op (op0, op1, mode); - if (tem) - return tem; - /* Convert (xor (and (not A) B) A) into A | B. */ if (GET_CODE (op0) == AND && GET_CODE (XEXP (op0, 0)) == NOT @@ -8750,46 +8684,6 @@ test_vec_merge (machine_mode mode) simplify_rtx (nvm)); } -/* Test that vector rotate formation works at RTL level. Try various - combinations of (REG << C) [|,^,+] (REG >> (<bitwidth> - C)). */ - -static void -test_vector_rotate (rtx reg) -{ - machine_mode mode = GET_MODE (reg); - unsigned bitwidth = GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT; - rtx plus_rtx = gen_rtx_PLUS (mode, reg, reg); - rtx lshftrt_amnt = GEN_INT (bitwidth - 1); - lshftrt_amnt = gen_const_vec_duplicate (mode, lshftrt_amnt); - rtx lshiftrt_rtx = gen_rtx_LSHIFTRT (mode, reg, lshftrt_amnt); - rtx rotate_rtx = gen_rtx_ROTATE (mode, reg, CONST1_RTX (mode)); - /* Test explicitly the case where ASHIFT (x, 1) is a PLUS (x, x). */ - ASSERT_RTX_EQ (rotate_rtx, - simplify_rtx (gen_rtx_IOR (mode, plus_rtx, lshiftrt_rtx))); - ASSERT_RTX_EQ (rotate_rtx, - simplify_rtx (gen_rtx_XOR (mode, plus_rtx, lshiftrt_rtx))); - ASSERT_RTX_EQ (rotate_rtx, - simplify_rtx (gen_rtx_PLUS (mode, plus_rtx, lshiftrt_rtx))); - - /* Don't go through every possible rotate amount to save execution time. - Multiple of BITS_PER_UNIT amounts could conceivably be simplified to - other bswap operations sometimes. Go through just the odd amounts. */ - for (unsigned i = 3; i < bitwidth - 2; i += 2) - { - rtx rot_amnt = gen_const_vec_duplicate (mode, GEN_INT (i)); - rtx ashift_rtx = gen_rtx_ASHIFT (mode, reg, rot_amnt); - lshftrt_amnt = gen_const_vec_duplicate (mode, GEN_INT (bitwidth - i)); - lshiftrt_rtx = gen_rtx_LSHIFTRT (mode, reg, lshftrt_amnt); - rotate_rtx = gen_rtx_ROTATE (mode, reg, rot_amnt); - ASSERT_RTX_EQ (rotate_rtx, - simplify_rtx (gen_rtx_IOR (mode, ashift_rtx, lshiftrt_rtx))); - ASSERT_RTX_EQ (rotate_rtx, - simplify_rtx (gen_rtx_XOR (mode, ashift_rtx, lshiftrt_rtx))); - ASSERT_RTX_EQ (rotate_rtx, - simplify_rtx (gen_rtx_PLUS (mode, ashift_rtx, lshiftrt_rtx))); - } -} - /* Test subregs of integer vector constant X, trying elements in the range [ELT_BIAS, ELT_BIAS + constant_lower_bound (NELTS)), where NELTS is the number of elements in X. Subregs involving @@ -8961,13 +8855,11 @@ test_vector_ops () { rtx scalar_reg = make_test_reg (GET_MODE_INNER (mode)); test_vector_ops_duplicate (mode, scalar_reg); - rtx vector_reg = make_test_reg (mode); if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT && maybe_gt (GET_MODE_NUNITS (mode), 2)) { test_vector_ops_series (mode, scalar_reg); test_vector_subregs (mode); - test_vector_rotate (vector_reg); } test_vec_merge (mode); }