Hello, when cse replaces registers in an insn it tries to avoid calls to validate_change, what causes trouble in some situations.
>From validate_canon_reg: /* If replacing pseudo with hard reg or vice versa, ensure the insn remains valid. Likewise if the insn has MATCH_DUPs. */ if (insn != 0 && new != 0 && REG_P (new) && REG_P (*xloc) && (((REGNO (new) < FIRST_PSEUDO_REGISTER) != (REGNO (*xloc) < FIRST_PSEUDO_REGISTER)) || GET_MODE (new) != GET_MODE (*xloc) || (insn_code = recog_memoized (insn)) < 0 || insn_data[insn_code].n_dups > 0)) validate_change (insn, xloc, new, 1); else *xloc = new; Lets assume the following instruction: [rA + rB] = [rA + rB] & 3; canon_regs likes to replace rA with HARD reg RC and rB with another pseudo rD. So we have 4 resulting changes: 1. SRC rB -> rD 2. SRC rA -> RC 3. DEST rB -> rD 4. DEST rA -> RC Lets assume that the insn already has been recognized. Then the first change is done without calling validate_change using the 'else' branch. The second change replaces a pseudo with an hard reg so validate_change is called. For the third change validate_change is used because the last change has set the recog_memoized flag for the insn to -1. And the last change again replaces a pseudo with an hard reg and therefore uses validate_change. The resulting change group therefore contains only the last 3 changes. If the subsequent call to apply_change_group fails we end up with: [rA + rB] = [rA + rD] & 3; Which now could still be invalid as it is on s390 because we want MEM operands in these kind of instructions to be the same on both sides. I would propose to always do the changes via validate_change what would trivially fix this issue. But as usual there will be people who care much more about compile time than I do and they will probably come up with a better solution. Bye, -Andreas-