diff options
author | Segher Boessenkool <segher@kernel.crashing.org> | 2016-10-28 22:56:28 +0200 |
---|---|---|
committer | Segher Boessenkool <segher@gcc.gnu.org> | 2016-10-28 22:56:28 +0200 |
commit | 9a5e1efcaca6305711e7d44b355e98c923f27c6d (patch) | |
tree | 8021e705f33c93434b854873987fa541d49d8007 | |
parent | a5742b01585d78d5e9c39e8dbc9cfce7796af492 (diff) | |
download | gcc-9a5e1efcaca6305711e7d44b355e98c923f27c6d.zip gcc-9a5e1efcaca6305711e7d44b355e98c923f27c6d.tar.gz gcc-9a5e1efcaca6305711e7d44b355e98c923f27c6d.tar.bz2 |
combine: Improve change_zero_ext (fixes PR71847)
This improves a few things in change_zero_ext. Firstly, it should use
the passed in pattern in recog_for_combine, not the pattern of the insn
(they are not the same if the whole pattern was replaced). Secondly,
it handled zero_ext of a subreg, but with hard registers we do not get
a subreg, instead the mode of the reg is changed. So this handles that.
Thirdly, after changing a zero_ext to an AND, the resulting RTL may become
non-canonical, like (ior (ashift ..) (and ..)); the AND should be first,
it is commutative. And lastly, zero_extract as a set_dest wasn't handled
at all, but now it is.
This fixes the testcase in PR71847, and improves code generation in some
other edge cases too.
PR target/71847
* combine.c (change_zero_ext): Handle zero_ext of hard registers.
Swap commutative operands in new RTL if needed. Handle zero_ext
in the set_dest.
(recog_for_combine): Pass *pnewpat to change_zero_ext instead of
PATTERN (insn).
From-SVN: r241664
-rw-r--r-- | gcc/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/combine.c | 55 |
2 files changed, 60 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4302280..32f6435 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2016-10-28 Segher Boessenkool <segher@kernel.crashing.org> + + PR target/71847 + * combine.c (change_zero_ext): Handle zero_ext of hard registers. + Swap commutative operands in new RTL if needed. Handle zero_ext + in the set_dest. + (recog_for_combine): Pass *pnewpat to change_zero_ext instead of + PATTERN (insn). + 2016-10-28 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org> Kugan Vivekanandarajah <kuganv@linaro.org> Jim Wilson <jim.wilson@linaro.org> diff --git a/gcc/combine.c b/gcc/combine.c index 64413b4..60a127f 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -11106,9 +11106,10 @@ recog_for_combine_1 (rtx *pnewpat, rtx_insn *insn, rtx *pnotes) Return whether anything was so changed. */ static bool -change_zero_ext (rtx *src) +change_zero_ext (rtx pat) { bool changed = false; + rtx *src = &SET_SRC (pat); subrtx_ptr_iterator::array_type array; FOR_EACH_SUBRTX_PTR (iter, array, src, NONCONST) @@ -11140,6 +11141,14 @@ change_zero_ext (rtx *src) size = GET_MODE_PRECISION (GET_MODE (XEXP (x, 0))); x = SUBREG_REG (XEXP (x, 0)); } + else if (GET_CODE (x) == ZERO_EXTEND + && SCALAR_INT_MODE_P (mode) + && REG_P (XEXP (x, 0)) + && HARD_REGISTER_P (XEXP (x, 0))) + { + size = GET_MODE_PRECISION (GET_MODE (XEXP (x, 0))); + x = gen_rtx_REG (mode, REGNO (XEXP (x, 0))); + } else continue; @@ -11150,6 +11159,44 @@ change_zero_ext (rtx *src) changed = true; } + if (changed) + FOR_EACH_SUBRTX_PTR (iter, array, src, NONCONST) + { + rtx x = **iter; + if (COMMUTATIVE_ARITH_P (x) + && swap_commutative_operands_p (XEXP (x, 0), XEXP (x, 1))) + { + rtx tem = XEXP (x, 0); + SUBST (XEXP (x, 0), XEXP (x, 1)); + SUBST (XEXP (x, 1), tem); + } + } + + rtx *dst = &SET_DEST (pat); + if (GET_CODE (*dst) == ZERO_EXTRACT + && REG_P (XEXP (*dst, 0)) + && CONST_INT_P (XEXP (*dst, 1)) + && CONST_INT_P (XEXP (*dst, 2))) + { + rtx reg = XEXP (*dst, 0); + int width = INTVAL (XEXP (*dst, 1)); + int offset = INTVAL (XEXP (*dst, 2)); + machine_mode mode = GET_MODE (reg); + int reg_width = GET_MODE_PRECISION (mode); + if (BITS_BIG_ENDIAN) + offset = reg_width - width - offset; + + 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)); + rtx z = simplify_gen_binary (IOR, mode, x, y); + SUBST (SET_DEST (pat), reg); + SUBST (SET_SRC (pat), z); + + changed = true; + } + return changed; } @@ -11172,7 +11219,7 @@ change_zero_ext (rtx *src) static int recog_for_combine (rtx *pnewpat, rtx_insn *insn, rtx *pnotes) { - rtx pat = PATTERN (insn); + rtx pat = *pnewpat; int insn_code_number = recog_for_combine_1 (pnewpat, insn, pnotes); if (insn_code_number >= 0 || check_asm_operands (pat)) return insn_code_number; @@ -11181,7 +11228,7 @@ recog_for_combine (rtx *pnewpat, rtx_insn *insn, rtx *pnotes) bool changed = false; if (GET_CODE (pat) == SET) - changed = change_zero_ext (&SET_SRC (pat)); + changed = change_zero_ext (pat); else if (GET_CODE (pat) == PARALLEL) { int i; @@ -11189,7 +11236,7 @@ recog_for_combine (rtx *pnewpat, rtx_insn *insn, rtx *pnotes) { rtx set = XVECEXP (pat, 0, i); if (GET_CODE (set) == SET) - changed |= change_zero_ext (&SET_SRC (set)); + changed |= change_zero_ext (set); } } |