Message ID | 56537379.4030101@redhat.com |
---|---|
State | New |
Headers | show |
> As I mentioned in a prior message on the subject, this is only a problem > when the source/dest of the extension are the same. When the > source/dest of the extension are different, we only optimize when the > original set and extension are in the same block and we verify that all > affected registers are not set/used between the original set and the > extension. > Bootstrapped and regression tested on x86_64-linux-gnu. Also tested > execute.exp on rl78 with no regressions. Ok. Bernd
Jeff Law <law@redhat.com> writes: > @@ -1080,6 +1070,18 @@ add_removable_extension (const_rtx expr, rtx_insn *insn, > } > } > > + /* Fourth, if the extended version occupies more registers than the > + original and the source of the extension is the same hard register > + as the destination of the extension, then we can not eliminate > + the extension without deep analysis, so just punt. > + > + We allow this when the registers are different because the > + code in combine_reaching_defs will handle that case correctly. */ > + if ((HARD_REGNO_NREGS (REGNO (dest), mode) > + != HARD_REGNO_NREGS (REGNO (reg), GET_MODE (reg))) > + && REGNO (dest) == REGNO (reg)) > + return; > + > /* Then add the candidate to the list and insert the reaching definitions > into the definition map. */ > ext_cand e = {expr, code, mode, insn}; I might be wrong, but the check looks specific to little-endian. Would it make sense to use reg_overlap_mentioned_p instead of the REGNO check? Thanks, Richard
On 12/01/2015 12:32 PM, Richard Sandiford wrote: > Jeff Law <law@redhat.com> writes: >> @@ -1080,6 +1070,18 @@ add_removable_extension (const_rtx expr, rtx_insn *insn, >> } >> } >> >> + /* Fourth, if the extended version occupies more registers than the >> + original and the source of the extension is the same hard register >> + as the destination of the extension, then we can not eliminate >> + the extension without deep analysis, so just punt. >> + >> + We allow this when the registers are different because the >> + code in combine_reaching_defs will handle that case correctly. */ >> + if ((HARD_REGNO_NREGS (REGNO (dest), mode) >> + != HARD_REGNO_NREGS (REGNO (reg), GET_MODE (reg))) >> + && REGNO (dest) == REGNO (reg)) >> + return; >> + >> /* Then add the candidate to the list and insert the reaching definitions >> into the definition map. */ >> ext_cand e = {expr, code, mode, insn}; > > I might be wrong, but the check looks specific to little-endian. Would > it make sense to use reg_overlap_mentioned_p instead of the REGNO check? Agreed. Testing in progress now... jeff
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e560746..29ed4e4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2015-11-18 Nick Clifton <nickc@redhat.com> + Jeff Law <law@redhat.com> + + * ree.c (add_removable_extension): Avoid mis-optimizing cases where + the source/dest of the target extension require a different number of + hard registers. + (combine_set_extension): Remove #if 0 code. + 2015-11-20 Jim Wilson <jim.wilson@linaro.org> * tree-vect-data-refs.c (compare_tree): Call STRIP_NOPS. diff --git a/gcc/ree.c b/gcc/ree.c index b8436f2..f3b79e0 100644 --- a/gcc/ree.c +++ b/gcc/ree.c @@ -332,16 +332,6 @@ combine_set_extension (ext_cand *cand, rtx_insn *curr_insn, rtx *orig_set) else new_reg = gen_rtx_REG (cand->mode, REGNO (SET_DEST (*orig_set))); -#if 0 - /* Rethinking test. Temporarily disabled. */ - /* We're going to be widening the result of DEF_INSN, ensure that doing so - doesn't change the number of hard registers needed for the result. */ - if (HARD_REGNO_NREGS (REGNO (new_reg), cand->mode) - != HARD_REGNO_NREGS (REGNO (SET_DEST (*orig_set)), - GET_MODE (SET_DEST (*orig_set)))) - return false; -#endif - /* Merge constants by directly moving the constant into the register under some conditions. Recall that RTL constants are sign-extended. */ if (GET_CODE (orig_src) == CONST_INT @@ -1080,6 +1070,18 @@ add_removable_extension (const_rtx expr, rtx_insn *insn, } } + /* Fourth, if the extended version occupies more registers than the + original and the source of the extension is the same hard register + as the destination of the extension, then we can not eliminate + the extension without deep analysis, so just punt. + + We allow this when the registers are different because the + code in combine_reaching_defs will handle that case correctly. */ + if ((HARD_REGNO_NREGS (REGNO (dest), mode) + != HARD_REGNO_NREGS (REGNO (reg), GET_MODE (reg))) + && REGNO (dest) == REGNO (reg)) + return; + /* Then add the candidate to the list and insert the reaching definitions into the definition map. */ ext_cand e = {expr, code, mode, insn};