aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSegher Boessenkool <segher@kernel.crashing.org>2016-10-28 22:56:28 +0200
committerSegher Boessenkool <segher@gcc.gnu.org>2016-10-28 22:56:28 +0200
commit9a5e1efcaca6305711e7d44b355e98c923f27c6d (patch)
tree8021e705f33c93434b854873987fa541d49d8007
parenta5742b01585d78d5e9c39e8dbc9cfce7796af492 (diff)
downloadgcc-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/ChangeLog9
-rw-r--r--gcc/combine.c55
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);
}
}