This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: SRA bit-field optimization
- From: Alexandre Oliva <aoliva at redhat dot com>
- To: "John David Anglin" <dave at hiauly1 dot hia dot nrc dot ca>
- Cc: richard dot guenther at gmail dot com, zippel at linux-m68k dot org, bernds_cb1 at t-online dot de, dnovillo at acm dot org, dberlin at dberlin dot org, gcc-patches at gcc dot gnu dot org, pinskia at gmail dot com, ebotcazou at adacore dot com, rsandifo at nildram dot co dot uk
- Date: Sun, 07 Oct 2007 20:43:17 -0300
- Subject: Re: SRA bit-field optimization
- References: <200710062105.l96L5d05013819@hiauly1.hia.nrc.ca> <87k5pzhp01.fsf@firetop.home>
On Oct 6, 2007, Richard Sandiford <rsandifo@nildram.co.uk> wrote:
> Ah, thanks. I did have a quick look at it, and it seemed to be caused
> by a missing conversion at the tree level. Expand was being given
> a BIT_AND_EXPR with a DImode-typed result and HImode-typed operand.
> I didn't try to track down where it was coming from. So it does seem
> to be a tree-level bug after all.
Yep, fixed in the revised patch below.
It also fixes the endianness problem that was hitting machines that
had BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN, that caused the 20031211-1.c
and other regressions. I remember having noticed at some point in the
development of the bit-field SRA patch that I was using the wrong
endianness macro and changing it, but BITS_BIG_ENDIAN wasn't what I
was looking for. Doh.
I haven't given this patch much testing yet, but the two new changes
are obviously correct and do make progress. I'm starting a test run
on a just-built mipsisa32-elf uberbaum tree, after having finally
figured out why dejagnu wasn't finding newlib (my uberbaum source tree
contained links to gcc and srcware sub-dirs, but site.exp set srcdir
with the pathname of the gcc source tree, rather than that of the
uberbaum tree, doesn't this bite anyone else?)
Ok to install if it passes bootstrap on x86_64-linux-gnu?
for gcc/ChangeLog
from Alexandre Oliva <aoliva@redhat.com>
* tree-sra.c (instantiate_element): Use BYTES_BIG_ENDIAN for
bit-field layout.
(sra_build_assignment): Likewise. Set up mask depending on
precision, not type.
(sra_build_bf_assignment): Use BYTES_BIG_ENDIAN. Don't overflow
computing bit masks. Fix type mismatch when applying negated
mask.
(sra_build_elt_assignment): Don't view-convert from signed to
unsigned.
(sra_explode_bitfield_assignment): Use bit-field type if
possible. Use BYTES_BIG_ENDIAN.
Index: gcc/tree-sra.c
===================================================================
--- gcc/tree-sra.c.orig 2007-10-06 08:46:59.000000000 -0300
+++ gcc/tree-sra.c 2007-10-07 20:20:11.000000000 -0300
@@ -1275,7 +1275,7 @@ instantiate_element (struct sra_elt *elt
elt->in_bitfld_block = 1;
elt->replacement = build3 (BIT_FIELD_REF, elt->type, var,
DECL_SIZE (var),
- BITS_BIG_ENDIAN
+ BYTES_BIG_ENDIAN
? size_binop (MINUS_EXPR,
TYPE_SIZE (elt->type),
DECL_SIZE (var))
@@ -2140,7 +2140,7 @@ sra_build_assignment (tree dst, tree src
cst2 = size_binop (PLUS_EXPR, TREE_OPERAND (src, 1),
TREE_OPERAND (src, 2));
- if (BITS_BIG_ENDIAN)
+ if (BYTES_BIG_ENDIAN)
{
maxshift = size_binop (MINUS_EXPR, TYPE_SIZE (TREE_TYPE (var)), cst);
minshift = size_binop (MINUS_EXPR, TYPE_SIZE (TREE_TYPE (var)), cst2);
@@ -2168,7 +2168,7 @@ sra_build_assignment (tree dst, tree src
list = NULL;
cst2 = size_binop (MINUS_EXPR, maxshift, minshift);
- if (tree_int_cst_equal (cst2, TYPE_SIZE (utype)))
+ if (TREE_INT_CST_LOW (cst2) == TYPE_PRECISION (utype))
{
unsignedp = true;
mask = NULL_TREE;
@@ -2322,7 +2322,7 @@ sra_build_bf_assignment (tree dst, tree
fold_convert (bitsizetype, TREE_OPERAND (dst, 1)),
cst);
- if (BITS_BIG_ENDIAN)
+ if (BYTES_BIG_ENDIAN)
{
maxshift = size_binop (MINUS_EXPR, TYPE_SIZE (TREE_TYPE (var)), cst);
minshift = size_binop (MINUS_EXPR, TYPE_SIZE (TREE_TYPE (var)), cst2);
@@ -2343,8 +2343,14 @@ sra_build_bf_assignment (tree dst, tree
utype = unsigned_type_for (type);
mask = build_int_cst_wide (utype, 1, 0);
- cst = int_const_binop (LSHIFT_EXPR, mask, maxshift, true);
- cst2 = int_const_binop (LSHIFT_EXPR, mask, minshift, true);
+ if (TREE_INT_CST_LOW (maxshift) == TYPE_PRECISION (utype))
+ cst = build_int_cst_wide (utype, 0, 0);
+ else
+ cst = int_const_binop (LSHIFT_EXPR, mask, maxshift, true);
+ if (integer_zerop (minshift))
+ cst2 = mask;
+ else
+ cst2 = int_const_binop (LSHIFT_EXPR, mask, minshift, true);
mask = int_const_binop (MINUS_EXPR, cst, cst2, true);
mask = fold_build1 (BIT_NOT_EXPR, utype, mask);
@@ -2508,13 +2514,13 @@ sra_build_elt_assignment (struct sra_elt
{
list = NULL;
- if (!INTEGRAL_TYPE_P (TREE_TYPE (src))
- || !TYPE_UNSIGNED (TREE_TYPE (src)))
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (src)))
src = fold_build1 (VIEW_CONVERT_EXPR,
lang_hooks.types.type_for_size
(TREE_INT_CST_LOW
(TYPE_SIZE (TREE_TYPE (src))),
1), src);
+ gcc_assert (TYPE_UNSIGNED (TREE_TYPE (src)));
tmp = make_rename_temp (TREE_TYPE (src), "SR");
stmt = build_gimple_modify_stmt (tmp, src);
@@ -2976,16 +2982,20 @@ sra_explode_bitfield_assignment (tree va
if (fld->replacement)
{
- tree infld, invar, st;
+ tree infld, invar, st, type;
infld = fld->replacement;
+ type = TREE_TYPE (infld);
+ if (TYPE_PRECISION (type) != TREE_INT_CST_LOW (flen))
+ type = lang_hooks.types.type_for_size (TREE_INT_CST_LOW (flen), 1);
+
if (TREE_CODE (infld) == BIT_FIELD_REF)
{
fpos = size_binop (PLUS_EXPR, fpos, TREE_OPERAND (infld, 2));
infld = TREE_OPERAND (infld, 0);
}
- else if (BITS_BIG_ENDIAN && DECL_P (fld->element)
+ else if (BYTES_BIG_ENDIAN && DECL_P (fld->element)
&& !tree_int_cst_equal (TYPE_SIZE (TREE_TYPE (infld)),
DECL_SIZE (fld->element)))
{
@@ -2995,10 +3005,7 @@ sra_explode_bitfield_assignment (tree va
DECL_SIZE (fld->element));
}
- infld = fold_build3 (BIT_FIELD_REF,
- lang_hooks.types.type_for_size
- (TREE_INT_CST_LOW (flen), 1),
- infld, flen, fpos);
+ infld = fold_build3 (BIT_FIELD_REF, type, infld, flen, fpos);
BIT_FIELD_REF_UNSIGNED (infld) = 1;
invar = size_binop (MINUS_EXPR, flp.field_pos, bpos);
@@ -3006,8 +3013,7 @@ sra_explode_bitfield_assignment (tree va
invar = size_binop (PLUS_EXPR, invar, flp.overlap_pos);
invar = size_binop (PLUS_EXPR, invar, vpos);
- invar = fold_build3 (BIT_FIELD_REF, TREE_TYPE (infld),
- var, flen, invar);
+ invar = fold_build3 (BIT_FIELD_REF, type, var, flen, invar);
BIT_FIELD_REF_UNSIGNED (invar) = 1;
if (to_var)
--
Alexandre Oliva http://www.lsd.ic.unicamp.br/~oliva/
FSF Latin America Board Member http://www.fsfla.org/
Red Hat Compiler Engineer aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist oliva@{lsd.ic.unicamp.br, gnu.org}