[Bug middle-end/11264] LROTATE_EXPR/RROTATE_EXPR misexpanded by middle-end/back-end for bitfields
mtodorov at alu dot hr
gcc-bugzilla@gcc.gnu.org
Sat Jul 12 11:36:00 GMT 2003
PLEASE REPLY TO gcc-bugzilla@gcc.gnu.org ONLY, *NOT* gcc-bugs@gcc.gnu.org.
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11264
------- Additional Comments From mtodorov at alu dot hr 2003-07-12 11:36 -------
Little progress:
================
We've traced it down to this code, gcc/expmed.c, that's unchanges until
gcc-20030709 snapshot (please see bellow):
NOTE that GET_MODE_BITSIZE (mode) when calculating suplementary shift count
for rotation emulation can get only information about the size of the
"container" of the variable.
NBAE, it appears to me that information about the number of bits of bitfield
is by now lost, and that the next power of two (8, 32, 64) is used
when calculating i.e.
ROR (A, N) = A >> N | A << (C - N)
where C equals 8, 16, 32 or 64.
This is of course incorrect for bitfields of size i.e. 11, or 42, when
*they* need to be rotated.
/* If you might think rotations aren't useful, they appear to be. Having
the ability that back-end generates a single rotate instruction instead
of emulating the above is a great advantage.
However NOTE that the above EMULATION isn't correct by definition for
N >= bitsize, where we'd naturally expect things to go circular.
This prevents front-end from emitting efficient rotation code for GPC,
since we have to double the amount of work by adding another N MOD P
(P = precision), which can expand in something less useful.
Ideally, back-end should do this N MOD P for us, then we'd have it only
when it's really needed, and ROR (A, N) for 8-bit, 16-bit or 32-bit
A would truly be expanded into a single ror (or vice versa rol).
Sorry if this was lenghty */
-------------------------------------------------------------------------------
else if (methods == OPTAB_LIB_WIDEN)
{
/* If we have been unable to open-code this by a rotation,
do it as the IOR of two shifts. I.e., to rotate A
by N bits, compute (A << N) | ((unsigned) A >> (C - N))
where C is the bitsize of A.
It is theoretically possible that the target machine might
not be able to perform either shift and hence we would
be making two libcalls rather than just the one for the
shift (similarly if IOR could not be done). We will allow
this extremely unlikely lossage to avoid complicating the
code below. */
rtx subtarget = target == shifted ? 0 : target;
rtx temp1;
tree type = TREE_TYPE (amount);
tree new_amount = make_tree (type, op1);
tree other_amount
= fold (build (MINUS_EXPR, type,
convert (type,
build_int_2 (GET_MODE_BITSIZE (mode),
0)),
amount));
shifted = force_reg (mode, shifted);
temp = expand_shift (left ? LSHIFT_EXPR : RSHIFT_EXPR,
mode, shifted, new_amount, subtarget, 1);
temp1 = expand_shift (left ? RSHIFT_EXPR : LSHIFT_EXPR,
mode, shifted, other_amount, 0, 1);
return expand_binop (mode, ior_optab, temp, temp1, target,
unsignedp, methods);
}
More information about the Gcc-bugs
mailing list