In a given test case with 128 bit mmx intrinsics, routine
make_compound_operation (in combine.c) attempts to do a sign-extract
of the middle 64bit of the 128 bit (TImode) register. Pattern we have
is:
(lshiftrt:TI (ashift:TI (subreg:TI (reg/v:V2DI 75
[ vu16YPrediction3 ]) 0) (const_int 32 [0x20]))
(const_int 64 [0x40]))
And here is the code which attempts to do this:
case LSHIFTRT:
....
/* ... fall through ... */
case ASHIFTRT:
lhs = XEXP (x, 0);
rhs = XEXP (x, 1);
/* If we have (ashiftrt (ashift foo C1) C2) with C2 >= C1,
this is a SIGN_EXTRACT. */
=> if (GET_CODE (rhs) == CONST_INT
&& GET_CODE (lhs) == ASHIFT
&& GET_CODE (XEXP (lhs, 1)) == CONST_INT
&& INTVAL (rhs) >= INTVAL (XEXP (lhs, 1)))
{
new = make_compound_operation (XEXP (lhs, 0), next_code);
new = make_extraction (mode, new,
INTVAL (rhs) - INTVAL (XEXP (lhs, 1)),
NULL_RTX, mode_width - INTVAL (rhs),
code == LSHIFTRT, 0, in_code ==
COMPARE);
....
This results in gen_rtx_SUBREG asserting. We can't really do this
extraction when the extraction mode (DImode in this case) is not
properly aligned within its original mode. In other words,
gen_rtx_SUBREG attempts to generate an illegal rtl; such as:
(subreg:DI (reg/v:V2DI 75 [ vu16YPrediction3 ]) 4)
and asserts. Following patch avoids this problem. If this is OK, I
will submit a patch when fsf mainline is unfrozen.
- fariborz ([EMAIL PROTECTED])
Index: combine.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/combine.c,v
retrieving revision 1.475.2.5
diff -c -p -r1.475.2.5 combine.c
*** combine.c 26 Aug 2005 22:36:52 -0000 1.475.2.5
--- combine.c 22 Sep 2005 19:52:02 -0000
*************** make_extraction (enum machine_mode mode,
*** 6197,6203 ****
/* Avoid creating invalid subregs, for example when
simplifying (x>>32)&255. */
! if (final_word >= GET_MODE_SIZE (inner_mode))
return NULL_RTX;
new = gen_rtx_SUBREG (tmode, inner, final_word);
--- 6197,6204 ----
/* Avoid creating invalid subregs, for example when
simplifying (x>>32)&255. */
! if (final_word >= GET_MODE_SIZE (inner_mode)
! || (final_word % GET_MODE_SIZE (tmode)) != 0)
return NULL_RTX;
new = gen_rtx_SUBREG (tmode, inner, final_word);