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:

Reply via email to