Jiong Wang <jiong.w...@arm.com> writes: > + /* If we have > + > + (ior (lshiftrt A imm1) (and (ashiftrt (A imm2)) mask)) > + > + where imm1 = imm2 + 1 > + mask = ((1 << imm1) - 1) << (mode_size (A) - imm1) > + > + then we may simplify this into > + > + (ashiftrt A imm1). > + > + For example: > + > + (ior:DI (lshiftrt:DI (reg:DI 79 [ data ]) > + (const_int 14 [0xe])) > + (and:DI (ashiftrt:DI (reg:DI 79 [ data ]) > + (const_int 13 [0xd])) > + (const_int -1125899906842624 [0xfffc000000000000]))). > + > + is actually: > + > + (ashiftrt:DI (reg:DI 79 [ data ]) (const_int 14 [0xe])). > + > + There is another form: > + > + (ior (lshiftrt A imm1) > + (ashift (subreg (sign_extend A) high_offset) imm2) > + > + where imm1 + imm2 == mode_size (A) could be simplified into > + > + (ashiftrt A imm1). */ > + > + if (GET_CODE (op1) == LSHIFTRT) > + { > + opleft = op1; > + opright = op0; > + } > + else > + { > + opright = op1; > + opleft = op0; > + } > + > + if (GET_CODE (opleft) == LSHIFTRT > + && GET_CODE (opright) == ASHIFT > + && CONST_INT_P (XEXP (opleft, 1)) > + && CONST_INT_P (XEXP (opright, 1)) > + && (INTVAL (XEXP (opleft, 1)) + INTVAL (XEXP (opright, 1))) > + == GET_MODE_SIZE (GET_MODE (XEXP (opleft, 0))) > + && GET_CODE (XEXP (opright, 0)) == SUBREG > + && GET_CODE (XEXP (XEXP (opright, 0), 0)) == SIGN_EXTEND > + && (SUBREG_BYTE (XEXP (opright, 0)) > + == subreg_highpart_offset (GET_MODE (XEXP (opright, 0)), > + GET_MODE (XEXP (XEXP (opright, 0), > + 0)))) > + && rtx_equal_p (XEXP (opleft, 0), XEXP (XEXP (XEXP (opright, 0), 0), > + 0)) > + && !side_effects_p (XEXP (opleft, 0)) > + && have_insn_for (ASHIFTRT, mode)) > + return simplify_gen_binary (ASHIFTRT, mode, XEXP (opleft, 0), > + XEXP (opleft, 1)); > + > + if (GET_CODE (opleft) == LSHIFTRT > + && GET_CODE (opright) == AND > + && CONST_INT_P (XEXP (opleft, 1)) > + && CONST_INT_P (XEXP (opright, 1)) > + && GET_CODE (XEXP (opright, 0)) == ASHIFTRT > + && CONST_INT_P (XEXP (XEXP (opright, 0), 1)) > + && rtx_equal_p (XEXP (opleft, 0), XEXP (XEXP (opright, 0), 0)) > + && !side_effects_p (XEXP (opleft, 0)) > + && have_insn_for (ASHIFTRT, mode)) > + { > + int lshiftrt_imm = INTVAL (XEXP (opleft, 1)); > + HOST_WIDE_INT mask_nonzero_part, and_mask = INTVAL (XEXP (opright, > 1)); > + int ashiftrt_imm, t_zero, l_one; > + > + if (width < HOST_BITS_PER_WIDE_INT) > + and_mask &= ((unsigned HOST_WIDE_INT) 1 << width) - 1; > + > + if (!and_mask) > + return opleft; > + > + ashiftrt_imm = INTVAL (XEXP (XEXP (opright, 0), 1)); > +#if GCC_VERSION >= 3004 > + t_zero = (width <= HOST_BITS_PER_INT > + ? __builtin_ctz (and_mask) > + : (width <= HOST_BITS_PER_LONG > + ? __builtin_ctzl (and_mask) > + : __builtin_ctzll (and_mask))); > +#else > + t_zero = 0; > + while (((~and_mask) >> t_zero) & 1) > + ++t_zero; > +#endif > + mask_nonzero_part = (((unsigned HOST_WIDE_INT) and_mask) >> t_zero); > +#if GCC_VERSION >= 3400 > + l_one = (width <= HOST_BITS_PER_INT > + ? __builtin_popcount (mask_nonzero_part) > + : (width <= HOST_BITS_PER_LONG > + ? __builtin_popcountl (mask_nonzero_part) > + : __builtin_popcountll (mask_nonzero_part))); > +#else > + /* calculate the number of leading 1-bits. > + we use _popcount above, because the second condition check > + of "if" below will make sure there is no gap between > + those 1-bits. */ > + l_one = sizeof (and_mask) * CHAR_BIT; > + while ((and_mask >> (l_one - 1)) & 1) > + --l_one; > + l_one = sizeof (and_mask) * CHAR_BIT - l_one; > +#endif > + > + if ((ashiftrt_imm + 1) == lshiftrt_imm > + && (mask_nonzero_part > + == ((HOST_WIDE_INT_C (1) << (ashiftrt_imm + 1)) - 1)) > + && lshiftrt_imm == l_one) > + return simplify_gen_binary (ASHIFTRT, mode, XEXP (opleft, 0), > + XEXP (opleft, 1)); > + } > + > tem = simplify_byte_swapping_operation (code, mode, op0, op1); > if (tem) > return tem;
Please do this using wi:: instead, which in particular should make the popcount stuff easier. E.g. the first large "if" would probably be: if (GET_CODE (opleft) == LSHIFTRT && GET_CODE (opright) == ASHIFT --> && CONST_SCALAR_INT_P (XEXP (opleft, 1)) --> && CONST_SCALAR_INT_P (XEXP (opright, 1)) --> && (wi::add (XEXP (opleft, 1), XEXP (opright, 1)) --> == GET_MODE_SIZE (GET_MODE (XEXP (opleft, 0))) && GET_CODE (XEXP (opright, 0)) == SUBREG && GET_CODE (XEXP (XEXP (opright, 0), 0)) == SIGN_EXTEND && (SUBREG_BYTE (XEXP (opright, 0)) == subreg_highpart_offset (GET_MODE (XEXP (opright, 0)), GET_MODE (XEXP (XEXP (opright, 0), 0)))) && rtx_equal_p (XEXP (opleft, 0), XEXP (XEXP (XEXP (opright, 0), 0), 0)) && !side_effects_p (XEXP (opleft, 0)) && have_insn_for (ASHIFTRT, mode)) return simplify_gen_binary (ASHIFTRT, mode, XEXP (opleft, 0), XEXP (opleft, 1)); The HOST_WIDE_INTs in the second big "if" would then be wide_ints. Thanks, Richard