summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/combine.c31
2 files changed, 30 insertions, 9 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 5fed9715531..761896fe6c5 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2016-11-10 Segher Boessenkool <segher@kernel.crashing.org>
+
+ PR rtl-optimization/78232
+ * combine.c (try_combine): Add a big comment about why reusing i2dest
+ is undesirable.
+ (change_zero_ext): Do not call simplify_gen_binary, do the
+ simplifications manually.
+
2016-11-10 Michael Meissner <meissner@linux.vnet.ibm.com>
* config/rs6000/rs6000.c (rs6000_hard_regno_mode_ok): If ISA 3.0,
diff --git a/gcc/combine.c b/gcc/combine.c
index 69020561c31..6ffa387a95c 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -3528,6 +3528,15 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
{
machine_mode new_mode = GET_MODE (SET_DEST (newpat));
+ /* ??? Reusing i2dest without resetting the reg_stat entry for it
+ (temporarily, until we are committed to this instruction
+ combination) does not work: for example, any call to nonzero_bits
+ on the register (from a splitter in the MD file, for example)
+ will get the old information, which is invalid.
+
+ Since nowadays we can create registers during combine just fine,
+ we should just create a new one here, not reuse i2dest. */
+
/* First try to split using the original register as a
scratch register. */
parallel = gen_rtx_PARALLEL (VOIDmode,
@@ -11133,8 +11142,10 @@ change_zero_ext (rtx pat)
if (BITS_BIG_ENDIAN)
start = GET_MODE_PRECISION (mode) - size - start;
- x = simplify_gen_binary (LSHIFTRT, mode,
- XEXP (x, 0), GEN_INT (start));
+ if (start)
+ x = gen_rtx_LSHIFTRT (mode, XEXP (x, 0), GEN_INT (start));
+ else
+ x = XEXP (x, 0);
}
else if (GET_CODE (x) == ZERO_EXTEND
&& SCALAR_INT_MODE_P (mode)
@@ -11190,16 +11201,18 @@ change_zero_ext (rtx pat)
if (BITS_BIG_ENDIAN)
offset = reg_width - width - offset;
+ rtx x, y, z, w;
wide_int mask = wi::shifted_mask (offset, width, true, reg_width);
- rtx x = gen_rtx_AND (mode, reg, immed_wide_int_const (mask, mode));
- rtx y = simplify_gen_binary (ASHIFT, mode, SET_SRC (pat),
- GEN_INT (offset));
wide_int mask2 = wi::shifted_mask (offset, width, false, reg_width);
- y = simplify_gen_binary (AND, mode, y,
- immed_wide_int_const (mask2, mode));
- rtx z = simplify_gen_binary (IOR, mode, x, y);
+ x = gen_rtx_AND (mode, reg, immed_wide_int_const (mask, mode));
+ if (offset)
+ y = gen_rtx_ASHIFT (mode, SET_SRC (pat), GEN_INT (offset));
+ else
+ y = SET_SRC (pat);
+ z = gen_rtx_AND (mode, y, immed_wide_int_const (mask2, mode));
+ w = gen_rtx_IOR (mode, x, z);
SUBST (SET_DEST (pat), reg);
- SUBST (SET_SRC (pat), z);
+ SUBST (SET_SRC (pat), w);
changed = true;
}