aboutsummaryrefslogtreecommitdiff
path: root/gcc/cse.c
diff options
context:
space:
mode:
authorKugan Vivekanandarajah <kuganv@linaro.org>2015-07-12 11:16:30 +0000
committerKugan Vivekanandarajah <kugan@gcc.gnu.org>2015-07-12 11:16:30 +0000
commit7f7379f6f4f28376ac4fa9a807217f1fec2488fc (patch)
tree6635ab0b12302db27b1fd7effdbb88af0fd00813 /gcc/cse.c
parent01169386a0f51405866e190bc836d6a1883a684f (diff)
downloadgcc-7f7379f6f4f28376ac4fa9a807217f1fec2488fc.zip
gcc-7f7379f6f4f28376ac4fa9a807217f1fec2488fc.tar.gz
gcc-7f7379f6f4f28376ac4fa9a807217f1fec2488fc.tar.bz2
cse.c (cse_insn): Calculate src_eqv for ZERO_EXTRACT.
gcc/ChangeLog: 2015-07-12 Kugan Vivekanandarajah <kuganv@linaro.org> * cse.c (cse_insn): Calculate src_eqv for ZERO_EXTRACT. * emit-rtl.c (set_for_reg_notes): Allow ZERO_EXTRACT to set REG_EQUAL note. From-SVN: r225721
Diffstat (limited to 'gcc/cse.c')
-rw-r--r--gcc/cse.c49
1 files changed, 42 insertions, 7 deletions
diff --git a/gcc/cse.c b/gcc/cse.c
index 255c4db..b06c669 100644
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -4524,14 +4524,49 @@ cse_insn (rtx_insn *insn)
canonicalize_insn (insn, &sets, n_sets);
/* If this insn has a REG_EQUAL note, store the equivalent value in SRC_EQV,
- if different, or if the DEST is a STRICT_LOW_PART. The latter condition
- is necessary because SRC_EQV is handled specially for this case, and if
- it isn't set, then there will be no equivalence for the destination. */
+ if different, or if the DEST is a STRICT_LOW_PART/ZERO_EXTRACT. The
+ latter condition is necessary because SRC_EQV is handled specially for
+ this case, and if it isn't set, then there will be no equivalence
+ for the destination. */
if (n_sets == 1 && REG_NOTES (insn) != 0
- && (tem = find_reg_note (insn, REG_EQUAL, NULL_RTX)) != 0
- && (! rtx_equal_p (XEXP (tem, 0), SET_SRC (sets[0].rtl))
- || GET_CODE (SET_DEST (sets[0].rtl)) == STRICT_LOW_PART))
- src_eqv = copy_rtx (XEXP (tem, 0));
+ && (tem = find_reg_note (insn, REG_EQUAL, NULL_RTX)) != 0)
+ {
+ if ((! rtx_equal_p (XEXP (tem, 0), SET_SRC (sets[0].rtl)))
+ || GET_CODE (SET_DEST (sets[0].rtl)) == STRICT_LOW_PART)
+ src_eqv = copy_rtx (XEXP (tem, 0));
+
+ /* If DEST is of the form ZERO_EXTACT, as in:
+ (set (zero_extract:SI (reg:SI 119)
+ (const_int 16 [0x10])
+ (const_int 16 [0x10]))
+ (const_int 51154 [0xc7d2]))
+ REG_EQUAL note will specify the value of register (reg:SI 119) at this
+ point. Note that this is different from SRC_EQV. We can however
+ calculate SRC_EQV with the position and width of ZERO_EXTRACT. */
+ else if (GET_CODE (SET_DEST (sets[0].rtl)) == ZERO_EXTRACT
+ && CONST_INT_P (src_eqv)
+ && CONST_INT_P (XEXP (SET_DEST (sets[0].rtl), 1))
+ && CONST_INT_P (XEXP (SET_DEST (sets[0].rtl), 2)))
+ {
+ rtx dest_reg = XEXP (SET_DEST (sets[0].rtl), 0);
+ rtx width = XEXP (SET_DEST (sets[0].rtl), 1);
+ rtx pos = XEXP (SET_DEST (sets[0].rtl), 2);
+ HOST_WIDE_INT val = INTVAL (src_eqv);
+ HOST_WIDE_INT mask;
+ unsigned int shift;
+ if (BITS_BIG_ENDIAN)
+ shift = GET_MODE_PRECISION (GET_MODE (dest_reg))
+ - INTVAL (pos) - INTVAL (width);
+ else
+ shift = INTVAL (pos);
+ if (INTVAL (width) == HOST_BITS_PER_WIDE_INT)
+ mask = ~(HOST_WIDE_INT) 0;
+ else
+ mask = ((HOST_WIDE_INT) 1 << INTVAL (width)) - 1;
+ val = (val >> shift) & mask;
+ src_eqv = GEN_INT (val);
+ }
+ }
/* Set sets[i].src_elt to the class each source belongs to.
Detect assignments from or to volatile things