[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