It turns out that the assertion checks I added in my last combine patch
trigger on about every target but the ones I tested. ;-) These
assertions tested for invalid zero_extract and sign_extract expressions,
where the initial and/or final positions are out of the first operand's
bounds.
Some of these failures (PR25890) are caused by combine trying to
synthesize invalid shifts. These could be easily fixed in combine itself.
Some other failures however are caused by bitfield operations. Expand
is more than happy to create QImode memory accesses independent of the
width of the bitfield. Fixing this is a mess because some machine
descriptions, in turn, *expect* this to be true and use a
(match_operand:QI 0 "memory_operand") in their extv/extzv patterns. In
other word, this would require the rework of the insv/extv/extzv
patterns that was mentioned a while ago. This is not appropriate for a
build-breaking bug, during the slush, and while I have little time to
devote to FSF GCC development.
For this reason I'm inclined to disable combine's transformations, and
return a (clobber (const_int 0)), in presence of "invalid" extractions.
The attached patch does exactly this. I'm bootstrapping it overnight,
but I'll post it right now so that people affected by the bug can also
test it.
Ok for mainline if it passes?
Paolo
2006-01-23 Paolo Bonzini <[EMAIL PROTECTED]>
PR rtl-optimization/25890
PR rtl-optimization/25905
* combine.c (expand_compound_operation, expand_field_assignment):
Fail if the bitfield's final position is out of bounds.
Index: combine.c
===================================================================
--- combine.c (revision 109978)
+++ combine.c (working copy)
@@ -5640,8 +5642,9 @@ expand_compound_operation (rtx x)
len = INTVAL (XEXP (x, 1));
pos = INTVAL (XEXP (x, 2));
- /* This should stay within the object being extracted, fail. */
- gcc_assert (len + pos <= GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))));
+ /* This should stay within the object being extracted, fail otherwise.
*/
+ if (len + pos > GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))))
+ return x;
if (BITS_BIG_ENDIAN)
pos = GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))) - len - pos;
@@ -5800,9 +5803,9 @@ expand_field_assignment (rtx x)
pos = XEXP (SET_DEST (x), 2);
/* A constant position should stay within the width of INNER. */
- if (GET_CODE (pos) == CONST_INT)
- gcc_assert (INTVAL (pos) + len
- <= GET_MODE_BITSIZE (GET_MODE (inner)));
+ if (GET_CODE (pos) == CONST_INT
+ && INTVAL (pos) + len > GET_MODE_BITSIZE (GET_MODE (inner)))
+ break;
if (BITS_BIG_ENDIAN)
{