Message ID | 20141027204720.GZ10376@tucnak.redhat.com |
---|---|
State | New |
Headers | show |
On 10/27/14 14:47, Jakub Jelinek wrote: > Hi! > > The following testcase is miscompiled in 4.8+ on x86_64 at -O2+, > because REE widens for ZERO_EXTEND mode on > (set (reg:QI ax) (const_int -1)) instruction to SImode, but doesn't > adjust REG_EQUAL note of (const_int -1) also to (const_int 0xff) > like it changes the pattern. > > The following patch attempts to adjust the notes if they are CONST_INT, > or drop otherwise (not sure if it would be desirable to emit > a ZERO_EXTEND of the previous content of the note), and both through > validate_change, so that if we give up later on, it is undone. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? > What about 4.9.2 (after release) and 4.8.x? > > 2014-10-27 Jakub Jelinek <jakub@redhat.com> > > PR rtl-optimization/63659 > * ree.c (update_reg_equal_equiv_notes): New function. > (combine_set_extension, transform_ifelse): Use it. > > * gcc.c-torture/execute/pr63659.c: New test. Does this do the right thing in the case where there's multiple reaching definitions and one of those reaching definitions turns out to be non-combinable, while some other has a fixable REG_EQUAL note? Don't we have to separate the check for a fixable note from the actual changing of the note? Jeff
On Wed, Oct 29, 2014 at 09:47:33PM -0600, Jeff Law wrote: > On 10/27/14 14:47, Jakub Jelinek wrote: > >Hi! > > > >The following testcase is miscompiled in 4.8+ on x86_64 at -O2+, > >because REE widens for ZERO_EXTEND mode on > >(set (reg:QI ax) (const_int -1)) instruction to SImode, but doesn't > >adjust REG_EQUAL note of (const_int -1) also to (const_int 0xff) > >like it changes the pattern. > > > >The following patch attempts to adjust the notes if they are CONST_INT, > >or drop otherwise (not sure if it would be desirable to emit > >a ZERO_EXTEND of the previous content of the note), and both through > >validate_change, so that if we give up later on, it is undone. > > > >Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? > >What about 4.9.2 (after release) and 4.8.x? > > > >2014-10-27 Jakub Jelinek <jakub@redhat.com> > > > > PR rtl-optimization/63659 > > * ree.c (update_reg_equal_equiv_notes): New function. > > (combine_set_extension, transform_ifelse): Use it. > > > > * gcc.c-torture/execute/pr63659.c: New test. > Does this do the right thing in the case where there's multiple reaching > definitions and one of those reaching definitions turns out to be > non-combinable, while some other has a fixable REG_EQUAL note? The changes to REG_EQUAL or REG_EQUIV notes (either adjustment of CONST_INT in it, or its removal) is tied to the changing of the insn holding it in the patch. So, if we revert the changes to the instruction, so it is again the original mode, we revert the changes to the notes too (either put back the old CONST_INT, or re-add the note). The granularity of changes in REE is combine_reaching_defs - each cand separately, if any insn needed to be changed for some cand fails to be changed, we revert all the changes for the cand in question (it is not possible to have only a subset of setters adjusted if we want to adjust the user(s)). So IMHO the right thing is what the patch does, tie it to the apply_change_group/cancel_changes that verifies or undoes the insn changes. > Don't we have to separate the check for a fixable note from the actual > changing of the note? Jakub
On 10/30/14 01:36, Jakub Jelinek wrote: > On Wed, Oct 29, 2014 at 09:47:33PM -0600, Jeff Law wrote: >> On 10/27/14 14:47, Jakub Jelinek wrote: >>> Hi! >>> >>> The following testcase is miscompiled in 4.8+ on x86_64 at -O2+, >>> because REE widens for ZERO_EXTEND mode on >>> (set (reg:QI ax) (const_int -1)) instruction to SImode, but doesn't >>> adjust REG_EQUAL note of (const_int -1) also to (const_int 0xff) >>> like it changes the pattern. >>> >>> The following patch attempts to adjust the notes if they are CONST_INT, >>> or drop otherwise (not sure if it would be desirable to emit >>> a ZERO_EXTEND of the previous content of the note), and both through >>> validate_change, so that if we give up later on, it is undone. >>> >>> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? >>> What about 4.9.2 (after release) and 4.8.x? >>> >>> 2014-10-27 Jakub Jelinek <jakub@redhat.com> >>> >>> PR rtl-optimization/63659 >>> * ree.c (update_reg_equal_equiv_notes): New function. >>> (combine_set_extension, transform_ifelse): Use it. >>> >>> * gcc.c-torture/execute/pr63659.c: New test. >> Does this do the right thing in the case where there's multiple reaching >> definitions and one of those reaching definitions turns out to be >> non-combinable, while some other has a fixable REG_EQUAL note? > > The changes to REG_EQUAL or REG_EQUIV notes (either adjustment of CONST_INT > in it, or its removal) is tied to the changing of the insn holding it > in the patch. Doh! I should have realized that. Objection removed. OK for the trunk. jeff
--- gcc/ree.c.jj 2014-10-22 15:52:18.000000000 +0200 +++ gcc/ree.c 2014-10-27 19:18:37.287412478 +0100 @@ -266,6 +266,50 @@ typedef struct ext_cand static int max_insn_uid; +/* Update or remove REG_EQUAL or REG_EQUIV notes for INSN. */ + +static bool +update_reg_equal_equiv_notes (rtx_insn *insn, enum machine_mode new_mode, + enum machine_mode old_mode, enum rtx_code code) +{ + rtx *loc = ®_NOTES (insn); + while (*loc) + { + enum reg_note kind = REG_NOTE_KIND (*loc); + if (kind == REG_EQUAL || kind == REG_EQUIV) + { + rtx orig_src = XEXP (*loc, 0); + /* Update equivalency constants. Recall that RTL constants are + sign-extended. */ + if (GET_CODE (orig_src) == CONST_INT + && HOST_BITS_PER_WIDE_INT >= GET_MODE_BITSIZE (new_mode)) + { + if (INTVAL (orig_src) >= 0 || code == SIGN_EXTEND) + /* Nothing needed. */; + else + { + /* Zero-extend the negative constant by masking out the + bits outside the source mode. */ + rtx new_const_int + = gen_int_mode (INTVAL (orig_src) + & GET_MODE_MASK (old_mode), + new_mode); + if (!validate_change (insn, &XEXP (*loc, 0), + new_const_int, true)) + return false; + } + loc = &XEXP (*loc, 1); + } + /* Drop all other notes, they assume a wrong mode. */ + else if (!validate_change (insn, loc, XEXP (*loc, 1), true)) + return false; + } + else + loc = &XEXP (*loc, 1); + } + return true; +} + /* Given a insn (CURR_INSN), an extension candidate for removal (CAND) and a pointer to the SET rtx (ORIG_SET) that needs to be modified, this code modifies the SET rtx to a new SET rtx that extends the @@ -287,6 +331,7 @@ static bool combine_set_extension (ext_cand *cand, rtx_insn *curr_insn, rtx *orig_set) { rtx orig_src = SET_SRC (*orig_set); + enum machine_mode orig_mode = GET_MODE (SET_DEST (*orig_set)); rtx new_set; rtx cand_pat = PATTERN (cand->insn); @@ -323,9 +368,8 @@ combine_set_extension (ext_cand *cand, r { /* Zero-extend the negative constant by masking out the bits outside the source mode. */ - enum machine_mode src_mode = GET_MODE (SET_DEST (*orig_set)); rtx new_const_int - = gen_int_mode (INTVAL (orig_src) & GET_MODE_MASK (src_mode), + = gen_int_mode (INTVAL (orig_src) & GET_MODE_MASK (orig_mode), GET_MODE (new_reg)); new_set = gen_rtx_SET (VOIDmode, new_reg, new_const_int); } @@ -364,7 +408,9 @@ combine_set_extension (ext_cand *cand, r /* This change is a part of a group of changes. Hence, validate_change will not try to commit the change. */ - if (validate_change (curr_insn, orig_set, new_set, true)) + if (validate_change (curr_insn, orig_set, new_set, true) + && update_reg_equal_equiv_notes (curr_insn, cand->mode, orig_mode, + cand->code)) { if (dump_file) { @@ -414,7 +460,9 @@ transform_ifelse (ext_cand *cand, rtx_in ifexpr = gen_rtx_IF_THEN_ELSE (cand->mode, cond, map_srcreg, map_srcreg2); new_set = gen_rtx_SET (VOIDmode, map_dstreg, ifexpr); - if (validate_change (def_insn, &PATTERN (def_insn), new_set, true)) + if (validate_change (def_insn, &PATTERN (def_insn), new_set, true) + && update_reg_equal_equiv_notes (def_insn, cand->mode, GET_MODE (dstreg), + cand->code)) { if (dump_file) { --- gcc/testsuite/gcc.c-torture/execute/pr63659.c.jj 2014-10-27 19:26:57.720902738 +0100 +++ gcc/testsuite/gcc.c-torture/execute/pr63659.c 2014-10-27 19:26:36.000000000 +0100 @@ -0,0 +1,29 @@ +/* PR rtl-optimization/63659 */ + +int a, b, c, *d = &b, g, h, i; +unsigned char e; +char f; + +int +main () +{ + while (a) + { + for (a = 0; a; a++) + for (; c; c++) + ; + if (i) + break; + } + + char j = c, k = -1, l; + l = g = j >> h; + f = l == 0 ? k : k % l; + e = 0 ? 0 : f; + *d = e; + + if (b != 255) + __builtin_abort (); + + return 0; +}