[RFC] combine: Improve change_zero_ext, call simplify_set afterwards.
Dominik Vogt
vogt@linux.vnet.ibm.com
Fri Dec 9 15:23:00 GMT 2016
There are several situations that combine.c:change_zero_ext does not
handle well yet. One of them is
(and:SI (subreg:SI (zero_extract:DI (reg:DI) ...) ...)
(with const_int operands to "and" and "zero_extract")
=>
(and:SI (subreg:SI (and:DI (lshiftrt:DI ...)))
with two nested "and"s. Another one is
(zero_extract:DI (foo:SI) ...)
which is ignored by change_zero_ext. Attached are two
experimental patches:
0001-*
Deal with mode expanding zero_extracts in change_zero_ext. The
patch looks good to me, but not sure whether endianness is
handled properly. Is the second argument of gen_rtx_SUBREG
correct?
0002-*
This is a work in progress with the goal of fixing the first
problem and similar ones by calling simplify_set after
change_zero_ext to get rid of the overly complex code. That
works fine in principle, but replaces back the (and (lshiftrt
...) ...) that change_zero_ext generates back into zero_extract
form. Fiddling with simplify_set and make_compound_operation* a
bit, trying to suppress undoing the transformations that
change_zero_ext has just done, resulted in the (unfinished)
patch.
As it's not clear to me whether this is a valid approach I'd
appreciate any advice on the patch or alternative ways of doing
that.
Ciao
Dominik ^_^ ^_^
--
Dominik Vogt
IBM Germany
-------------- next part --------------
>From 600ed3dadd5bc2568ab53be8466686abaf27ff3f Mon Sep 17 00:00:00 2001
From: Dominik Vogt <vogt@linux.vnet.ibm.com>
Date: Fri, 9 Dec 2016 02:48:30 +0100
Subject: [PATCH 1/2] combine: Handle mode expanding zero_extracts in
change_zero_ext.
Example:
(zero_extract:DI (reg:SI)
(const_int 24)
(const_int 0))
-->
(and:DI (subreg:DI (lshiftrt:SI (reg:SI) (const_int 8))
0)
(const_int 16777215))
---
gcc/combine.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/gcc/combine.c b/gcc/combine.c
index b429453..e14a08f 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -11237,18 +11237,24 @@ change_zero_ext (rtx pat)
if (GET_CODE (x) == ZERO_EXTRACT
&& CONST_INT_P (XEXP (x, 1))
&& CONST_INT_P (XEXP (x, 2))
- && GET_MODE (XEXP (x, 0)) == mode)
+ && (GET_MODE (XEXP (x, 0)) == mode
+ || GET_MODE_PRECISION (GET_MODE (XEXP (x, 0)))
+ < GET_MODE_PRECISION (mode)))
{
+ machine_mode inner_mode = GET_MODE (XEXP (x, 0));
+
size = INTVAL (XEXP (x, 1));
int start = INTVAL (XEXP (x, 2));
if (BITS_BIG_ENDIAN)
- start = GET_MODE_PRECISION (mode) - size - start;
+ start = GET_MODE_PRECISION (inner_mode) - size - start;
if (start)
- x = gen_rtx_LSHIFTRT (mode, XEXP (x, 0), GEN_INT (start));
+ x = gen_rtx_LSHIFTRT (inner_mode, XEXP (x, 0), GEN_INT (start));
else
x = XEXP (x, 0);
+ if (mode != inner_mode)
+ x = gen_rtx_SUBREG (mode, x, 0);
}
else if (GET_CODE (x) == ZERO_EXTEND
&& SCALAR_INT_MODE_P (mode)
--
2.3.0
-------------- next part --------------
>From 8566f5a551cfd98978577b24ff05e8341410a56f Mon Sep 17 00:00:00 2001
From: Dominik Vogt <vogt@linux.vnet.ibm.com>
Date: Fri, 9 Dec 2016 15:56:15 +0100
Subject: [PATCH 2/2] combine: Call simplify_set after change_zero_ext.
---
gcc/combine.c | 156 +++++++++++++++++++++++++++++++++++++++-------------------
1 file changed, 105 insertions(+), 51 deletions(-)
diff --git a/gcc/combine.c b/gcc/combine.c
index e14a08f..4c53fe1 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -431,12 +431,14 @@ static rtx *find_split_point (rtx *, rtx_insn *, bool);
static rtx subst (rtx, rtx, rtx, int, int, int);
static rtx combine_simplify_rtx (rtx, machine_mode, int, int);
static rtx simplify_if_then_else (rtx);
-static rtx simplify_set (rtx);
+static rtx simplify_set (rtx, bool);
static rtx simplify_logical (rtx);
static rtx expand_compound_operation (rtx);
static const_rtx expand_field_assignment (const_rtx);
static rtx make_extraction (machine_mode, rtx, HOST_WIDE_INT,
rtx, unsigned HOST_WIDE_INT, int, int, int);
+static rtx make_compound_operation_1 (rtx, enum rtx_code, bool);
+static rtx make_compound_operation_no_zero_ext (rtx, enum rtx_code);
static rtx extract_left_shift (rtx, int);
static int get_pos_from_mask (unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT *);
@@ -6186,7 +6188,7 @@ combine_simplify_rtx (rtx x, machine_mode op0_mode, int in_dest,
return expand_compound_operation (x);
case SET:
- return simplify_set (x);
+ return simplify_set (x, true);
case AND:
case IOR:
@@ -6564,10 +6566,12 @@ simplify_if_then_else (rtx x)
return x;
}
-/* Simplify X, a SET expression. Return the new expression. */
+/* Simplify X, a SET expression. Return the new expression.
+ Internally calls make_compound_operation_no_zero_ext instead of
+ make_compound_operation if ALLOW_ZERO_EXT is false. */
static rtx
-simplify_set (rtx x)
+simplify_set (rtx x, bool allow_zero_ext)
{
rtx src = SET_SRC (x);
rtx dest = SET_DEST (x);
@@ -6757,7 +6761,10 @@ simplify_set (rtx x)
{
/* Get SET_SRC in a form where we have placed back any
compound expressions. Then do the checks below. */
- src = make_compound_operation (src, SET);
+ if (allow_zero_ext)
+ src = make_compound_operation (src, SET);
+ else
+ src = make_compound_operation_no_zero_ext (src, SET);
SUBST (SET_SRC (x), src);
}
@@ -7793,12 +7800,15 @@ extract_left_shift (rtx x, int count)
- Return null. This tells the caller to recurse on *X_PTR with IN_CODE
equal to *NEXT_CODE_PTR, after which *X_PTR holds the final value.
- - Return a new rtx, which the caller returns directly. */
+ - Return a new rtx, which the caller returns directly.
+
+ If ALLOW_ZERO_EXT is false, skip transformations to
+ ZERO_EXTRACT and ZERO_EXTEND. */
static rtx
make_compound_operation_int (machine_mode mode, rtx *x_ptr,
enum rtx_code in_code,
- enum rtx_code *next_code_ptr)
+ enum rtx_code *next_code_ptr, bool allow_zero_ext)
{
rtx x = *x_ptr;
enum rtx_code next_code = *next_code_ptr;
@@ -7809,6 +7819,7 @@ make_compound_operation_int (machine_mode mode, rtx *x_ptr,
int i;
rtx tem;
bool equality_comparison = false;
+ int in_dest = allow_zero_ext ? 0 : 1;
if (in_code == EQ)
{
@@ -7831,7 +7842,8 @@ make_compound_operation_int (machine_mode mode, rtx *x_ptr,
HOST_WIDE_INT count = INTVAL (XEXP (x, 1));
HOST_WIDE_INT multval = HOST_WIDE_INT_1 << count;
- new_rtx = make_compound_operation (XEXP (x, 0), next_code);
+ new_rtx = make_compound_operation_1 (XEXP (x, 0), next_code,
+ allow_zero_ext);
if (GET_CODE (new_rtx) == NEG)
{
new_rtx = XEXP (new_rtx, 0);
@@ -7845,8 +7857,8 @@ make_compound_operation_int (machine_mode mode, rtx *x_ptr,
case PLUS:
lhs = XEXP (x, 0);
rhs = XEXP (x, 1);
- lhs = make_compound_operation (lhs, next_code);
- rhs = make_compound_operation (rhs, next_code);
+ lhs = make_compound_operation_1 (lhs, next_code, allow_zero_ext);
+ rhs = make_compound_operation_1 (rhs, next_code, allow_zero_ext);
if (GET_CODE (lhs) == MULT && GET_CODE (XEXP (lhs, 0)) == NEG)
{
tem = simplify_gen_binary (MULT, mode, XEXP (XEXP (lhs, 0), 0),
@@ -7873,8 +7885,8 @@ make_compound_operation_int (machine_mode mode, rtx *x_ptr,
case MINUS:
lhs = XEXP (x, 0);
rhs = XEXP (x, 1);
- lhs = make_compound_operation (lhs, next_code);
- rhs = make_compound_operation (rhs, next_code);
+ lhs = make_compound_operation_1 (lhs, next_code, allow_zero_ext);
+ rhs = make_compound_operation_1 (rhs, next_code, allow_zero_ext);
if (GET_CODE (rhs) == MULT && GET_CODE (XEXP (rhs, 0)) == NEG)
{
tem = simplify_gen_binary (MULT, mode, XEXP (XEXP (rhs, 0), 0),
@@ -7908,9 +7920,10 @@ make_compound_operation_int (machine_mode mode, rtx *x_ptr,
if (GET_CODE (XEXP (x, 0)) == LSHIFTRT
&& (i = exact_log2 (UINTVAL (XEXP (x, 1)) + 1)) >= 0)
{
- new_rtx = make_compound_operation (XEXP (XEXP (x, 0), 0), next_code);
+ new_rtx = make_compound_operation_1 (XEXP (XEXP (x, 0), 0), next_code,
+ allow_zero_ext);
new_rtx = make_extraction (mode, new_rtx, 0, XEXP (XEXP (x, 0), 1), i, 1,
- 0, in_code == COMPARE);
+ in_dest, in_code == COMPARE);
}
/* Same as previous, but for (subreg (lshiftrt ...)) in first op. */
@@ -7921,10 +7934,11 @@ make_compound_operation_int (machine_mode mode, rtx *x_ptr,
{
rtx inner_x0 = SUBREG_REG (XEXP (x, 0));
machine_mode inner_mode = GET_MODE (inner_x0);
- new_rtx = make_compound_operation (XEXP (inner_x0, 0), next_code);
+ new_rtx = make_compound_operation_1 (XEXP (inner_x0, 0), next_code,
+ allow_zero_ext);
new_rtx = make_extraction (inner_mode, new_rtx, 0,
XEXP (inner_x0, 1),
- i, 1, 0, in_code == COMPARE);
+ i, 1, in_dest, in_code == COMPARE);
if (new_rtx)
{
@@ -7943,9 +7957,10 @@ make_compound_operation_int (machine_mode mode, rtx *x_ptr,
its own. */
if (!new_rtx && i >= 0)
{
- new_rtx = make_compound_operation (XEXP (x, 0), next_code);
+ new_rtx = make_compound_operation_1 (XEXP (x, 0), next_code,
+ allow_zero_ext);
new_rtx = make_extraction (mode, new_rtx, 0, NULL_RTX, i, 1,
- 0, in_code == COMPARE);
+ in_dest, in_code == COMPARE);
}
}
/* Same as previous, but for (xor/ior (lshiftrt...) (lshiftrt...)). */
@@ -7961,7 +7976,8 @@ make_compound_operation_int (machine_mode mode, rtx *x_ptr,
XEXP (x, 1)),
gen_rtx_AND (mode, XEXP (XEXP (x, 0), 1),
XEXP (x, 1)));
- new_rtx = make_compound_operation (new_rtx, in_code);
+ new_rtx = make_compound_operation_1 (new_rtx, in_code,
+ allow_zero_ext);
}
/* If we are have (and (rotate X C) M) and C is larger than the number
@@ -7972,11 +7988,12 @@ make_compound_operation_int (machine_mode mode, rtx *x_ptr,
&& (i = exact_log2 (UINTVAL (XEXP (x, 1)) + 1)) >= 0
&& i <= INTVAL (XEXP (XEXP (x, 0), 1)))
{
- new_rtx = make_compound_operation (XEXP (XEXP (x, 0), 0), next_code);
+ new_rtx = make_compound_operation_1 (XEXP (XEXP (x, 0), 0), next_code,
+ allow_zero_ext);
new_rtx = make_extraction (mode, new_rtx,
(GET_MODE_PRECISION (mode)
- INTVAL (XEXP (XEXP (x, 0), 1))),
- NULL_RTX, i, 1, 0, in_code == COMPARE);
+ NULL_RTX, i, 1, in_dest, in_code == COMPARE);
}
/* On machines without logical shifts, if the operand of the AND is
@@ -7996,8 +8013,9 @@ make_compound_operation_int (machine_mode mode, rtx *x_ptr,
if ((INTVAL (XEXP (x, 1)) & ~mask) == 0)
SUBST (XEXP (x, 0),
gen_rtx_ASHIFTRT (mode,
- make_compound_operation
- (XEXP (XEXP (x, 0), 0), next_code),
+ make_compound_operation_1
+ (XEXP (XEXP (x, 0), 0), next_code,
+ allow_zero_ext),
XEXP (XEXP (x, 0), 1)));
}
@@ -8007,9 +8025,10 @@ make_compound_operation_int (machine_mode mode, rtx *x_ptr,
we are in a COMPARE. */
else if ((i = exact_log2 (UINTVAL (XEXP (x, 1)) + 1)) >= 0)
new_rtx = make_extraction (mode,
- make_compound_operation (XEXP (x, 0),
- next_code),
- 0, NULL_RTX, i, 1, 0, in_code == COMPARE);
+ make_compound_operation_1 (XEXP (x, 0),
+ next_code,
+ allow_zero_ext),
+ 0, NULL_RTX, i, 1, in_dest, in_code == COMPARE);
/* If we are in a comparison and this is an AND with a power of two,
convert this into the appropriate bit extract. */
@@ -8017,9 +8036,10 @@ make_compound_operation_int (machine_mode mode, rtx *x_ptr,
&& (i = exact_log2 (UINTVAL (XEXP (x, 1)))) >= 0
&& (equality_comparison || i < GET_MODE_PRECISION (mode) - 1))
new_rtx = make_extraction (mode,
- make_compound_operation (XEXP (x, 0),
- next_code),
- i, NULL_RTX, 1, 1, 0, 1);
+ make_compound_operation_1 (XEXP (x, 0),
+ next_code,
+ allow_zero_ext),
+ i, NULL_RTX, 1, 1, in_dest, 1);
/* If the one operand is a paradoxical subreg of a register or memory and
the constant (limited to the smaller mode) has only zero bits where
@@ -8041,10 +8061,11 @@ make_compound_operation_int (machine_mode mode, rtx *x_ptr,
mask = UINTVAL (XEXP (x, 1)) | (~nonzero_bits (sub, sub_mode));
if ((mask & mode_mask) == mode_mask)
{
- new_rtx = make_compound_operation (sub, next_code);
+ new_rtx = make_compound_operation_1 (sub, next_code,
+ allow_zero_ext);
new_rtx = make_extraction (mode, new_rtx, 0, 0,
GET_MODE_PRECISION (sub_mode),
- 1, 0, in_code == COMPARE);
+ 1, in_dest, in_code == COMPARE);
}
}
}
@@ -8060,9 +8081,9 @@ make_compound_operation_int (machine_mode mode, rtx *x_ptr,
&& (nonzero_bits (XEXP (x, 0), mode) & (1 << (mode_width - 1))) == 0)
{
new_rtx = gen_rtx_ASHIFTRT (mode,
- make_compound_operation (XEXP (x, 0),
- next_code),
- XEXP (x, 1));
+ make_compound_operation_1
+ (XEXP (x, 0), next_code, allow_zero_ext),
+ XEXP (x, 1));
break;
}
@@ -8081,11 +8102,13 @@ make_compound_operation_int (machine_mode mode, rtx *x_ptr,
&& INTVAL (XEXP (lhs, 1)) >= 0
&& INTVAL (rhs) < mode_width)
{
- new_rtx = make_compound_operation (XEXP (lhs, 0), next_code);
+ new_rtx = make_compound_operation_1 (XEXP (lhs, 0), next_code,
+ allow_zero_ext);
new_rtx = make_extraction (mode, new_rtx,
INTVAL (rhs) - INTVAL (XEXP (lhs, 1)),
NULL_RTX, mode_width - INTVAL (rhs),
- code == LSHIFTRT, 0, in_code == COMPARE);
+ code == LSHIFTRT, in_dest,
+ in_code == COMPARE);
break;
}
@@ -8102,9 +8125,10 @@ make_compound_operation_int (machine_mode mode, rtx *x_ptr,
&& INTVAL (rhs) < HOST_BITS_PER_WIDE_INT
&& INTVAL (rhs) < mode_width
&& (new_rtx = extract_left_shift (lhs, INTVAL (rhs))) != 0)
- new_rtx = make_extraction (mode, make_compound_operation (new_rtx, next_code),
+ new_rtx = make_extraction (mode, make_compound_operation_1
+ (new_rtx, next_code, allow_zero_ext),
0, NULL_RTX, mode_width - INTVAL (rhs),
- code == LSHIFTRT, 0, in_code == COMPARE);
+ code == LSHIFTRT, in_dest, in_code == COMPARE);
break;
@@ -8125,13 +8149,14 @@ make_compound_operation_int (machine_mode mode, rtx *x_ptr,
< GET_MODE_PRECISION (GET_MODE (inner)))
&& subreg_lowpart_p (x))
{
- new_rtx = make_compound_operation (XEXP (inner, 0), next_code);
+ new_rtx = make_compound_operation_1 (XEXP (inner, 0), next_code,
+ allow_zero_ext);
int width = GET_MODE_PRECISION (GET_MODE (inner))
- INTVAL (XEXP (inner, 1));
if (width > mode_width)
width = mode_width;
new_rtx = make_extraction (mode, new_rtx, 0, XEXP (inner, 1),
- width, 1, 0, in_code == COMPARE);
+ width, 1, in_dest, in_code == COMPARE);
break;
}
@@ -8150,7 +8175,7 @@ make_compound_operation_int (machine_mode mode, rtx *x_ptr,
>= GET_MODE_BITSIZE (mode))))
subreg_code = SET;
- tem = make_compound_operation (inner, subreg_code);
+ tem = make_compound_operation_1 (inner, subreg_code, allow_zero_ext);
simplified
= simplify_subreg (mode, tem, GET_MODE (inner), SUBREG_BYTE (x));
@@ -8167,7 +8192,8 @@ make_compound_operation_int (machine_mode mode, rtx *x_ptr,
/* If we have something other than a SUBREG, we might have
done an expansion, so rerun ourselves. */
if (GET_CODE (newer) != SUBREG)
- newer = make_compound_operation (newer, in_code);
+ newer = make_compound_operation_1 (newer, in_code,
+ allow_zero_ext);
/* force_to_mode can expand compounds. If it just re-expanded the
compound, use gen_lowpart to convert to the desired mode. */
@@ -8204,6 +8230,9 @@ make_compound_operation_int (machine_mode mode, rtx *x_ptr,
equivalent to ZERO_EXTRACT, SIGN_EXTRACT, ZERO_EXTEND, SIGN_EXTEND.
Form these expressions.
+ ZERO_EXTRACT and ZERO_EXTEND are only handled if ALLOW_ZERO_EXT
+ is true.
+
Return the new rtx, usually just X.
Also, for machines like the VAX that don't have logical shift insns,
@@ -8218,8 +8247,8 @@ make_compound_operation_int (machine_mode mode, rtx *x_ptr,
a comparison or a COMPARE against zero, it is COMPARE, or EQ if more
precisely it is an equality comparison against zero. */
-rtx
-make_compound_operation (rtx x, enum rtx_code in_code)
+static rtx
+make_compound_operation_1 (rtx x, enum rtx_code in_code, bool allow_zero_ext)
{
enum rtx_code code = GET_CODE (x);
const char *fmt;
@@ -8239,7 +8268,8 @@ make_compound_operation (rtx x, enum rtx_code in_code)
if (SCALAR_INT_MODE_P (GET_MODE (x)))
{
rtx new_rtx = make_compound_operation_int (GET_MODE (x), &x,
- in_code, &next_code);
+ in_code, &next_code,
+ allow_zero_ext);
if (new_rtx)
return new_rtx;
code = GET_CODE (x);
@@ -8248,9 +8278,9 @@ make_compound_operation (rtx x, enum rtx_code in_code)
/* Now recursively process each operand of this operation. We need to
handle ZERO_EXTEND specially so that we don't lose track of the
inner mode. */
- if (code == ZERO_EXTEND)
+ if (allow_zero_ext && code == ZERO_EXTEND)
{
- new_rtx = make_compound_operation (XEXP (x, 0), next_code);
+ new_rtx = make_compound_operation_1 (XEXP (x, 0), next_code, true);
tem = simplify_const_unary_operation (ZERO_EXTEND, GET_MODE (x),
new_rtx, GET_MODE (XEXP (x, 0)));
if (tem)
@@ -8263,19 +8293,35 @@ make_compound_operation (rtx x, enum rtx_code in_code)
for (i = 0; i < GET_RTX_LENGTH (code); i++)
if (fmt[i] == 'e')
{
- new_rtx = make_compound_operation (XEXP (x, i), next_code);
+ new_rtx = make_compound_operation_1 (XEXP (x, i), next_code,
+ allow_zero_ext);
SUBST (XEXP (x, i), new_rtx);
}
else if (fmt[i] == 'E')
for (j = 0; j < XVECLEN (x, i); j++)
{
- new_rtx = make_compound_operation (XVECEXP (x, i, j), next_code);
+ new_rtx = make_compound_operation_1 (XVECEXP (x, i, j), next_code,
+ allow_zero_ext);
SUBST (XVECEXP (x, i, j), new_rtx);
}
maybe_swap_commutative_operands (x);
return x;
}
+
+rtx
+make_compound_operation (rtx x, enum rtx_code in_code)
+{
+ return make_compound_operation_1 (x, in_code, true);
+}
+
+/* Like make_compound_operation but does not transform to
+ ZERO_EXTEND and ZERO_EXTRACT. */
+static rtx
+make_compound_operation_no_zero_ext (rtx x, enum rtx_code in_code)
+{
+ return make_compound_operation_1 (x, in_code, false);
+}
/* Given M see if it is a value that would select a field of bits
within an item, but not the entire word. Return -1 if not.
@@ -11352,7 +11398,11 @@ recog_for_combine (rtx *pnewpat, rtx_insn *insn, rtx *pnotes)
bool changed = false;
if (GET_CODE (pat) == SET)
- changed = change_zero_ext (pat);
+ {
+ changed = change_zero_ext (pat);
+ if (changed)
+ pat = simplify_set (pat, false);
+ }
else if (GET_CODE (pat) == PARALLEL)
{
int i;
@@ -11360,7 +11410,11 @@ 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);
+ if (change_zero_ext (set))
+ {
+ changed = true;
+ set = simplify_set (set, false);
+ }
}
}
--
2.3.0
More information about the Gcc-patches
mailing list