On Thu, Oct 13, 2011 at 2:45 PM, H.J. Lu <hjl.to...@gmail.com> wrote: > On Thu, Oct 13, 2011 at 2:30 PM, Richard Kenner > <ken...@vlsi1.ultra.nyu.edu> wrote: >>> It is because mask 0xffffffff is optimized to 0xfffffffc by keeping track >>> of non-zero bits in registers and the above code doesn't take that >>> into account. >> >> Then I'd suggest modifying that code so that it does rather than >> essentially duplicating it. But I'd recommend running some >> performance tests to verify that you're not pessimizing things when >> you do that: this stuff can be very tricky and you want to make sure >> that you're not converting something like (and X 3) into a bit >> extraction unnecessarily. >> > > But the current code converts (and X 3) into a bit extraction > since ((i = exact_log2 (UINTVAL (XEXP (x, 1)) + 1)) >= 0) is true > when UINTVAL (XEXP (x, 1)) == 3. Should we do it or not? >
I am testing this patch. The difference is it checks nonzero bits of the first operand. -- H.J. -- diff --git a/gcc/combine.c b/gcc/combine.c index 6c3b17c..598dee3 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -7739,16 +7739,6 @@ make_compound_operation (rtx x, enum rtx_code in_code) XEXP (XEXP (x, 0), 1))); } - /* If the constant is one less than a power of two, this might be - representable by an extraction even if no shift is present. - If it doesn't end up being a ZERO_EXTEND, we will ignore it unless - we are in a COMPARE. */ - else if ((i = exact_log2 (UINTVAL (XEXP (x, 1)) + 1)) >= 0) - new_rtx = make_extraction (mode, - make_compound_operation (XEXP (x, 0), - next_code), - 0, NULL_RTX, i, 1, 0, in_code == COMPARE); - /* If we are in a comparison and this is an AND with a power of two, convert this into the appropriate bit extract. */ else if (in_code == COMPARE @@ -7758,6 +7748,23 @@ make_compound_operation (rtx x, enum rtx_code in_code) next_code), i, NULL_RTX, 1, 1, 0, 1); + /* If we are (and (OP) M) and M is an extraction mask, this is an + extraction. */ + else + { + unsigned HOST_WIDE_INT nonzero = + nonzero_bits (XEXP (x, 0), GET_MODE (XEXP (x, 0))); + unsigned HOST_WIDE_INT mask = UINTVAL (XEXP (x, 1)); + unsigned HOST_WIDE_INT len = ceil_log2 (mask); + if ((nonzero & (((unsigned HOST_WIDE_INT) 1 << len) - 1)) + == (nonzero & mask)) + { + new_rtx = make_compound_operation (XEXP (x, 0), next_code); + new_rtx = make_extraction (mode, new_rtx, 0, NULL_RTX, + len, 1, 0, in_code == COMPARE); + } + } + break; case LSHIFTRT: