This bug has gone latent on the trunk; however, the problem still remains that cse will incorrectly simplify a ZERO/SIGN_EXTRACT in some cases.
ZERO/SIGN_EXTRACT are somewhat special in that if they are extracting from a memory operand, that memory operand will always have QImode regardless of the size of the extracted field. ie, the mode of the MEM in a ZERO/SIGN_EXTRACT does not really mean anything and the ZERO/SIGN_EXTRACT can read bits beyond QImode. So given a (mem:QI x) with an equivalence to (const_int 0) in the hash tables. If we have an extraction like (zero_extract:SI (mem:QI x) (const_int 0) (const_int 24)) CSE will substitute (const_int 0) for the MEM in the extraction resulting in (zero_extract:SI (const_int 0) (const_int 0) (const_int 24)) Which simplifies to (const_int 0) For REGs, the mode is the same as the operand of the insv/extv pattern, and may (or may not) more closely resemble reality depending on the target. The safe thing to do in CSE is to lookup the ZERO/SIGN_EXTRACT as a whole. Given the bug is latent and not currently a regression this will need to wait for the next stage1 development cycle.
diff --git a/gcc/cse.c b/gcc/cse.c index f7b477c..8ab48c4 100644 --- a/gcc/cse.c +++ b/gcc/cse.c @@ -3178,6 +3178,15 @@ fold_rtx (rtx x, rtx insn) { case MEM: case SUBREG: + /* The first operand of a SIGN/ZERO_EXTRACT has a different meaning + than it would in other contexts. Basically its mode does not + signify the size of the object read. That information is carried + by size operand. If we happen to have a MEM of the appropriate + mode in our tables with a constant value we could simplify the + extraction incorrectly if we allowed substitution of that value + for the MEM. */ + case ZERO_EXTRACT: + case SIGN_EXTRACT: if ((new_rtx = equiv_constant (x)) != NULL_RTX) return new_rtx; return x;