On 30 October 2013 02:47, Jeff Law <[email protected]> wrote:
> On 10/24/13 02:20, Zhenqiang Chen wrote:
>>
>> Hi,
>>
>> REG_INC note is lost in subreg2 pass when resolve_simple_move, which
>> might lead to wrong dependence for ira. e.g. In function
>> validate_equiv_mem of ira.c, it checks REG_INC note:
>>
>> for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
>> if ((REG_NOTE_KIND (note) == REG_INC
>> || REG_NOTE_KIND (note) == REG_DEAD)
>> && REG_P (XEXP (note, 0))
>> && reg_overlap_mentioned_p (XEXP (note, 0), memref))
>> return 0;
>>
>> Without REG_INC note, validate_equiv_mem will return a wrong result.
>>
>> Referhttps://bugs.launchpad.net/gcc-linaro/+bug/1243022 for more
>>
>> detail about a real case in kernel.
>>
>> Bootstrap and no make check regression on X86-64 and ARM.
>>
>> Is it OK for trunk and 4.8?
>>
>> Thanks!
>> -Zhenqiang
>>
>> ChangeLog:
>> 2013-10-24 Zhenqiang Chen<[email protected]>
>>
>> * lower-subreg.c (resolve_simple_move): Copy REG_INC note.
>>
>> testsuite/ChangeLog:
>> 2013-10-24 Zhenqiang Chen<[email protected]>
>>
>> * gcc.target/arm/lp1243022.c: New test.
>
> This clearly handles adding a note when the destination is a MEM with a side
> effect. What about cases where the side effect is associated with a load
> from memory rather than a store to memory?
Yes. We should handle load from memory.
>>
>>
>> lp1243022.patch
>>
>>
>> diff --git a/gcc/lower-subreg.c b/gcc/lower-subreg.c
>> index 57b4b3c..e710fa5 100644
>> --- a/gcc/lower-subreg.c
>> +++ b/gcc/lower-subreg.c
>> @@ -1056,6 +1056,22 @@ resolve_simple_move (rtx set, rtx insn)
>> mdest = simplify_gen_subreg (orig_mode, dest, GET_MODE (dest), 0);
>> minsn = emit_move_insn (real_dest, mdest);
>>
>> +#ifdef AUTO_INC_DEC
>> + /* Copy the REG_INC notes. */
>> + if (MEM_P (real_dest) && !(resolve_reg_p (real_dest)
>> + || resolve_subreg_p (real_dest)))
>> + {
>> + rtx note = find_reg_note (insn, REG_INC, NULL_RTX);
>> + if (note)
>> + {
>> + if (!REG_NOTES (minsn))
>> + REG_NOTES (minsn) = note;
>> + else
>> + add_reg_note (minsn, REG_INC, note);
>> + }
>> + }
>> +#endif
>
> If MINSN does not have any notes, then this results in MINSN and INSN
> sharing the note. Note carefully that notes are chained (see implementation
> of add_reg_note). Thus the sharing would result in MINSN and INSN actually
> sharing a chain of notes. I'm pretty sure that's not what you intended. I
> think you need to always use add_reg_note.
Yes. I should use add_reg_note.
Here is the updated patch:
diff --git a/gcc/lower-subreg.c b/gcc/lower-subreg.c
index ebf364f..16dfa62 100644
--- a/gcc/lower-subreg.c
+++ b/gcc/lower-subreg.c
@@ -967,7 +967,20 @@ resolve_simple_move (rtx set, rtx insn)
rtx reg;
reg = gen_reg_rtx (orig_mode);
+
+#ifdef AUTO_INC_DEC
+ {
+ rtx move = emit_move_insn (reg, src);
+ if (MEM_P (src))
+ {
+ rtx note = find_reg_note (insn, REG_INC, NULL_RTX);
+ if (note)
+ add_reg_note (move, REG_INC, XEXP (note, 0));
+ }
+ }
+#else
emit_move_insn (reg, src);
+#endif
src = reg;
}
@@ -1057,6 +1070,16 @@ resolve_simple_move (rtx set, rtx insn)
mdest = simplify_gen_subreg (orig_mode, dest, GET_MODE (dest), 0);
minsn = emit_move_insn (real_dest, mdest);
+#ifdef AUTO_INC_DEC
+ if (MEM_P (real_dest) && !(resolve_reg_p (real_dest)
+ || resolve_subreg_p (real_dest)))
+ {
+ rtx note = find_reg_note (insn, REG_INC, NULL_RTX);
+ if (note)
+ add_reg_note (minsn, REG_INC, XEXP (note, 0));
+ }
+#endif
+
smove = single_set (minsn);
gcc_assert (smove != NULL_RTX);