From: Segher Boessenkool Date: Thu, 10 Nov 2016 22:45:39 +0000 (+0100) Subject: combine: Do not call simplify from inside change_zero_ext (PR78232) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=071af74db674f3dc462ab8a25e091b74830fda2d;p=gcc.git combine: Do not call simplify from inside change_zero_ext (PR78232) When combine splits a three-insn combination into two instructions it can reuse i2dest for the temporary result of the first new instruction. However all information it has in reg_stat about that register will be stale. This results in the simplify_gen_binary calls in change_zero_ext using out-of-date information, which makes it think one of the ANDs generated there always results in 0, and it doesn't get better from there. This can also happen if a splitter in the MD uses nonzero_bits (for example). I tried to make the splitting code in combine save and restore the i2dest reg_stat info, but that causes one of the acats tests to fail. This whole reg_stat thing needs an overhaul, and/or we shouldn't reuse i2dest for unrelated purposes when splitting. This patch changes change_zero_ext to do the expected simplifications itself and not call simplify_gen_*. 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. From-SVN: r242059 --- 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 + + 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 * 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; }