@@ -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,26 @@ make_compound_operation (rtx x, enum rtx_code in_code)
next_code),
i, NULL_RTX, 1, 1, 0, 1);
+ /* If the constant is an extraction mask with the zero bits in
+ the first operand ignored, 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
+ {
+ 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: