[backport from gcc-4.8/trunk r186748 ] From: "Andreas Krebbel" Date: Fri, 20 Apr 2012 12:47:04 +0200 Subject: [PATCH] recog: Record also added clobbers in insn_invalid_p List-Archive: Hi, insn_invalid_p might add clobbers in order to match an instruction. Unfortunately that change is not recorded in the 'changes' array. So if it is decided to rollback the changes the added clobbers will stay. This is a problem if the back-end provides two (mostly) identical insn patterns, one of them with a clobber and the other without. Adding a clobber might allow to pick the other pattern. If this is part of a bigger change which is rolled back, the insn code will be set back to the old value but the clobbers won't be removed. The result is an insn where the code doesn't match the pattern. This currently breaks Ada bootstrap on s390x. The problem has been revealed by the recent fwprop change: http://gcc.gnu.org/ml/gcc-patches/2012-03/msg01269.html Fixed with the attached patch. Bootstrapped and regtested on s390x, ppc64 and x86_64. Ok for mainline? Bye, -Andreas- gcc/ 2012-04-24 Andreas Krebbel * recog.c (insn_invalid_p): Add IN_GROUP parameter and use validate_change to add clobbers if IN_GROUP is nonzero. (verify_changes): Call insn_invalid_p with IN_GROUP set to true. * recog.h (insn_invalid_p): Add IN_GROUP parameter to function prototype. * gcse.c (process_insert_insn): Call insn_invalid_p with IN_GROUP set to false. * config/s390/s390.c (insn_invalid_p): Likewise. --- gcc-4.6.3/gcc/config/s390/s390.c.~1~ 2011-07-20 15:36:11.000000000 +0200 +++ gcc-4.6.3/gcc/config/s390/s390.c 2012-09-09 14:53:14.000000000 +0200 @@ -4530,7 +4530,7 @@ s390_expand_addcc (enum rtx_code cmp_cod insn = gen_rtx_SET (VOIDmode, gen_rtx_REG (cc_mode, CC_REGNUM), gen_rtx_COMPARE (cc_mode, cmp_op0, cmp_op1)); /* We use insn_invalid_p here to add clobbers if required. */ - ret = insn_invalid_p (emit_insn (insn)); + ret = insn_invalid_p (emit_insn (insn), false); gcc_assert (!ret); /* Emit ALC instruction pattern. */ @@ -4602,7 +4602,7 @@ s390_expand_addcc (enum rtx_code cmp_cod insn = gen_rtx_SET (VOIDmode, gen_rtx_REG (cc_mode, CC_REGNUM), gen_rtx_COMPARE (cc_mode, cmp_op0, cmp_op1)); /* We use insn_invalid_p here to add clobbers if required. */ - ret = insn_invalid_p (emit_insn (insn)); + ret = insn_invalid_p (emit_insn (insn), false); gcc_assert (!ret); /* Emit SLB instruction pattern. */ --- gcc-4.6.3/gcc/gcse.c.~1~ 2011-02-03 07:04:04.000000000 +0100 +++ gcc-4.6.3/gcc/gcse.c 2012-09-09 14:53:14.000000000 +0200 @@ -3596,7 +3596,7 @@ process_insert_insn (struct expr *expr) { rtx insn = emit_insn (gen_rtx_SET (VOIDmode, reg, exp)); - if (insn_invalid_p (insn)) + if (insn_invalid_p (insn, false)) gcc_unreachable (); } --- gcc-4.6.3/gcc/recog.c.~1~ 2012-01-15 20:35:15.000000000 +0100 +++ gcc-4.6.3/gcc/recog.c 2012-09-09 14:53:14.000000000 +0200 @@ -287,10 +287,14 @@ canonicalize_change_group (rtx insn, rtx /* This subroutine of apply_change_group verifies whether the changes to INSN - were valid; i.e. whether INSN can still be recognized. */ + were valid; i.e. whether INSN can still be recognized. + + If IN_GROUP is true clobbers which have to be added in order to + match the instructions will be added to the current change group. + Otherwise the changes will take effect immediately. */ int -insn_invalid_p (rtx insn) +insn_invalid_p (rtx insn, bool in_group) { rtx pat = PATTERN (insn); int num_clobbers = 0; @@ -322,7 +326,10 @@ insn_invalid_p (rtx insn) newpat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (num_clobbers + 1)); XVECEXP (newpat, 0, 0) = pat; add_clobbers (newpat, icode); - PATTERN (insn) = pat = newpat; + if (in_group) + validate_change (insn, &PATTERN (insn), newpat, 1); + else + PATTERN (insn) = pat = newpat; } /* After reload, verify that all constraints are satisfied. */ @@ -391,7 +398,7 @@ verify_changes (int num) } else if (DEBUG_INSN_P (object)) continue; - else if (insn_invalid_p (object)) + else if (insn_invalid_p (object, true)) { rtx pat = PATTERN (object); --- gcc-4.6.3/gcc/recog.h.~1~ 2011-01-22 20:35:10.000000000 +0100 +++ gcc-4.6.3/gcc/recog.h 2012-09-09 14:53:14.000000000 +0200 @@ -79,7 +79,7 @@ extern int asm_operand_ok (rtx, const ch extern bool validate_change (rtx, rtx *, rtx, bool); extern bool validate_unshare_change (rtx, rtx *, rtx, bool); extern bool canonicalize_change_group (rtx insn, rtx x); -extern int insn_invalid_p (rtx); +extern int insn_invalid_p (rtx, bool); extern int verify_changes (int); extern void confirm_change_group (void); extern int apply_change_group (void);