Commit 9a5e1efc by Segher Boessenkool Committed by Segher Boessenkool

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
parent a5742b01
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> 2016-10-28 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
Kugan Vivekanandarajah <kuganv@linaro.org> Kugan Vivekanandarajah <kuganv@linaro.org>
Jim Wilson <jim.wilson@linaro.org> Jim Wilson <jim.wilson@linaro.org>
...@@ -11106,9 +11106,10 @@ recog_for_combine_1 (rtx *pnewpat, rtx_insn *insn, rtx *pnotes) ...@@ -11106,9 +11106,10 @@ recog_for_combine_1 (rtx *pnewpat, rtx_insn *insn, rtx *pnotes)
Return whether anything was so changed. */ Return whether anything was so changed. */
static bool static bool
change_zero_ext (rtx *src) change_zero_ext (rtx pat)
{ {
bool changed = false; bool changed = false;
rtx *src = &SET_SRC (pat);
subrtx_ptr_iterator::array_type array; subrtx_ptr_iterator::array_type array;
FOR_EACH_SUBRTX_PTR (iter, array, src, NONCONST) FOR_EACH_SUBRTX_PTR (iter, array, src, NONCONST)
...@@ -11140,6 +11141,14 @@ change_zero_ext (rtx *src) ...@@ -11140,6 +11141,14 @@ change_zero_ext (rtx *src)
size = GET_MODE_PRECISION (GET_MODE (XEXP (x, 0))); size = GET_MODE_PRECISION (GET_MODE (XEXP (x, 0)));
x = SUBREG_REG (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 else
continue; continue;
...@@ -11150,6 +11159,44 @@ change_zero_ext (rtx *src) ...@@ -11150,6 +11159,44 @@ change_zero_ext (rtx *src)
changed = true; 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; return changed;
} }
...@@ -11172,7 +11219,7 @@ change_zero_ext (rtx *src) ...@@ -11172,7 +11219,7 @@ change_zero_ext (rtx *src)
static int static int
recog_for_combine (rtx *pnewpat, rtx_insn *insn, rtx *pnotes) 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); int insn_code_number = recog_for_combine_1 (pnewpat, insn, pnotes);
if (insn_code_number >= 0 || check_asm_operands (pat)) if (insn_code_number >= 0 || check_asm_operands (pat))
return insn_code_number; return insn_code_number;
...@@ -11181,7 +11228,7 @@ recog_for_combine (rtx *pnewpat, rtx_insn *insn, rtx *pnotes) ...@@ -11181,7 +11228,7 @@ recog_for_combine (rtx *pnewpat, rtx_insn *insn, rtx *pnotes)
bool changed = false; bool changed = false;
if (GET_CODE (pat) == SET) if (GET_CODE (pat) == SET)
changed = change_zero_ext (&SET_SRC (pat)); changed = change_zero_ext (pat);
else if (GET_CODE (pat) == PARALLEL) else if (GET_CODE (pat) == PARALLEL)
{ {
int i; int i;
...@@ -11189,7 +11236,7 @@ recog_for_combine (rtx *pnewpat, rtx_insn *insn, rtx *pnotes) ...@@ -11189,7 +11236,7 @@ recog_for_combine (rtx *pnewpat, rtx_insn *insn, rtx *pnotes)
{ {
rtx set = XVECEXP (pat, 0, i); rtx set = XVECEXP (pat, 0, i);
if (GET_CODE (set) == SET) if (GET_CODE (set) == SET)
changed |= change_zero_ext (&SET_SRC (set)); changed |= change_zero_ext (set);
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment