diff options
author | Richard Sandiford <rdsandiford@googlemail.com> | 2014-05-28 08:41:27 +0000 |
---|---|---|
committer | Olivier Hainque <hainque@gcc.gnu.org> | 2014-05-28 08:41:27 +0000 |
commit | c8912e539b9060c3f4f037188374e2ccfa00666b (patch) | |
tree | cd95c321218af68818300b397eeb1456a6d823cc /gcc | |
parent | 9c6ab05f6a3f85c8d911e327677b83828daec840 (diff) | |
download | gcc-c8912e539b9060c3f4f037188374e2ccfa00666b.zip gcc-c8912e539b9060c3f4f037188374e2ccfa00666b.tar.gz gcc-c8912e539b9060c3f4f037188374e2ccfa00666b.tar.bz2 |
rtl.h (set_for_reg_notes): Declare.
2014-05-26 Richard Sandiford <rdsandiford@googlemail.com>
Olivier Hainque <hainque@adacore.com>
* rtl.h (set_for_reg_notes): Declare.
* emit-rtl.c (set_for_reg_notes): New function.
(set_unique_reg_note): Use it.
* optabs.c (add_equal_note): Likewise
Co-Authored-By: Olivier Hainque <hainque@adacore.com>
From-SVN: r210998
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/emit-rtl.c | 74 | ||||
-rw-r--r-- | gcc/optabs.c | 2 | ||||
-rw-r--r-- | gcc/rtl.h | 1 |
3 files changed, 52 insertions, 25 deletions
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index 5515244..3bf2ff7 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -5086,6 +5086,45 @@ gen_use (rtx x) return seq; } +/* Notes like REG_EQUAL and REG_EQUIV refer to a set in an instruction. + Return the set in INSN that such notes describe, or NULL if the notes + have no meaning for INSN. */ + +rtx +set_for_reg_notes (rtx insn) +{ + rtx pat, reg; + + if (!INSN_P (insn)) + return NULL_RTX; + + pat = PATTERN (insn); + if (GET_CODE (pat) == PARALLEL) + { + /* We do not use single_set because that ignores SETs of unused + registers. REG_EQUAL and REG_EQUIV notes really do require the + PARALLEL to have a single SET. */ + if (multiple_sets (insn)) + return NULL_RTX; + pat = XVECEXP (pat, 0, 0); + } + + if (GET_CODE (pat) != SET) + return NULL_RTX; + + reg = SET_DEST (pat); + + /* Notes apply to the contents of a STRICT_LOW_PART. */ + if (GET_CODE (reg) == STRICT_LOW_PART) + reg = XEXP (reg, 0); + + /* Check that we have a register. */ + if (!(REG_P (reg) || GET_CODE (reg) == SUBREG)) + return NULL_RTX; + + return pat; +} + /* Place a note of KIND on insn INSN with DATUM as the datum. If a note of this type already exists, remove it first. */ @@ -5098,39 +5137,26 @@ set_unique_reg_note (rtx insn, enum reg_note kind, rtx datum) { case REG_EQUAL: case REG_EQUIV: - /* Don't add REG_EQUAL/REG_EQUIV notes if the insn - has multiple sets (some callers assume single_set - means the insn only has one set, when in fact it - means the insn only has one * useful * set). */ - if (GET_CODE (PATTERN (insn)) == PARALLEL && multiple_sets (insn)) - { - gcc_assert (!note); - return NULL_RTX; - } + if (!set_for_reg_notes (insn)) + return NULL_RTX; /* Don't add ASM_OPERAND REG_EQUAL/REG_EQUIV notes. It serves no useful purpose and breaks eliminate_regs. */ if (GET_CODE (datum) == ASM_OPERANDS) return NULL_RTX; - - if (note) - { - XEXP (note, 0) = datum; - df_notes_rescan (insn); - return note; - } break; default: - if (note) - { - XEXP (note, 0) = datum; - return note; - } break; } - add_reg_note (insn, kind, datum); + if (note) + XEXP (note, 0) = datum; + else + { + add_reg_note (insn, kind, datum); + note = REG_NOTES (insn); + } switch (kind) { @@ -5142,14 +5168,14 @@ set_unique_reg_note (rtx insn, enum reg_note kind, rtx datum) break; } - return REG_NOTES (insn); + return note; } /* Like set_unique_reg_note, but don't do anything unless INSN sets DST. */ rtx set_dst_reg_note (rtx insn, enum reg_note kind, rtx datum, rtx dst) { - rtx set = single_set (insn); + rtx set = set_for_reg_notes (insn); if (set && SET_DEST (set) == dst) return set_unique_reg_note (insn, kind, datum); diff --git a/gcc/optabs.c b/gcc/optabs.c index 9af5227..ca1c194 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -228,7 +228,7 @@ add_equal_note (rtx insns, rtx target, enum rtx_code code, rtx op0, rtx op1) return 0; } - set = single_set (last_insn); + set = set_for_reg_notes (last_insn); if (set == NULL_RTX) return 1; @@ -2197,6 +2197,7 @@ extern enum machine_mode choose_hard_reg_mode (unsigned int, unsigned int, bool); /* In emit-rtl.c */ +extern rtx set_for_reg_notes (rtx); extern rtx set_unique_reg_note (rtx, enum reg_note, rtx); extern rtx set_dst_reg_note (rtx, enum reg_note, rtx, rtx); extern void set_insn_deleted (rtx); |