[Bug middle-end/11264] New: LROTATE_EXPR/RROTATE_EXPR misexpanded by middle-end/back-end

mtodorov at alu dot hr gcc-bugzilla@gcc.gnu.org
Fri Jun 20 13:43: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

           Summary: LROTATE_EXPR/RROTATE_EXPR misexpanded by middle-
                    end/back-end
           Product: gcc
           Version: 3.2.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: middle-end
        AssignedTo: unassigned@gcc.gnu.org
        ReportedBy: mtodorov@alu.hr
                CC: frank@g-n-u.de,gcc-bugs@gcc.gnu.org
  GCC host triplet: i686-pc-linux-gnu

In a function RotateLeft/RotateRight of GNU Pascal
LROTATE_EXPR/RROTATE_EXPR is emitted as
tree node. Backend does wrong things when TYPE_PRECISION(op0) mod 8 <> 0
It rotates the bitfield on next power of 2 bits ... and some output
bits are lost. The size of rotation result is defined as the size of 1st
operand, when operation is RotateLeft(op, cnt);

I've spoken to Frank Heckenbach of GNU Pascal team, and he expressed
opinion the bug is back-end-related, and I should file a report.

Thank you for your help, so the GCC would be even better.

Mirsad Todorovac

------------------------------------------------------------------------

The problem is I don't know of any gcc's function or operator using
LROTATE_EXPR or RROTATE_EXPR, so I think there will be a little problem
with explaining the bug, as direct example is hard to produce here so
you could reproduce it there (the bug is GCC-backed related, and the
example is in Pascal language, sorry)!

The simple program rotates left $801 for various rotate counts.
The output is, however, flawed:

-----------------------------------------------------------------------------
program testrl(output);
uses String;

const bitsize = 12;

type c12 = Cardinal attribute(Size = bitsize);
type c10 = Cardinal attribute(Size = 10);

var rec: packed record
           i, k: c12;
           j : c10;
         end;
begin
  with rec do
    begin
      i := (1 shl (bitsize - 1)) or 1;
      j := 0;
      repeat
        k := RotateLeft (i, j);
        WriteLn (Integer2StringBaseExt (i, 2, 16, False, False),
                 ' rol ', j:2, ' = ',
                 Integer2StringBaseExt (k, 2, 16, False, False));
        j := j + 1;
      until j = 32
    end
end.

---------------------------------------------------------------------------

OUTPUT:
---------------------------------------------------------------------------
magrf:~/pascal/gcc-3.2.1/gcc/p/test> a.out
0000100000000001 rol  0 = 0000100000000001
0000100000000001 rol  1 = 0000000000000010 (!)
0000100000000001 rol  2 = 0000000000000100 (!)
0000100000000001 rol  3 = 0000000000001000 (!)
0000100000000001 rol  4 = 0000000000010000 (!)
0000100000000001 rol  5 = 0000000000100001
0000100000000001 rol  6 = 0000000001000010
0000100000000001 rol  7 = 0000000010000100
0000100000000001 rol  8 = 0000000100001000
0000100000000001 rol  9 = 0000001000010000
0000100000000001 rol 10 = 0000010000100000
0000100000000001 rol 11 = 0000100001000000
0000100000000001 rol 12 = 0000100000000001
0000100000000001 rol 13 = 0000000000000010
0000100000000001 rol 14 = 0000000000000100
0000100000000001 rol 15 = 0000000000001000
0000100000000001 rol 16 = 0000000000010000
0000100000000001 rol 17 = 0000000000100001
0000100000000001 rol 18 = 0000000001000010
0000100000000001 rol 19 = 0000000010000100
0000100000000001 rol 20 = 0000000100001000
0000100000000001 rol 21 = 0000001000010000
0000100000000001 rol 22 = 0000010000100000
0000100000000001 rol 23 = 0000100001000000
0000100000000001 rol 24 = 0000100000000001
0000100000000001 rol 25 = 0000000000000010
0000100000000001 rol 26 = 0000000000000100
0000100000000001 rol 27 = 0000000000001000
0000100000000001 rol 28 = 0000000000010000
0000100000000001 rol 29 = 0000000000100001
0000100000000001 rol 30 = 0000000001000010
0000100000000001 rol 31 = 0000000010000100
magrf:~/pascal/gcc-3.2.1/gcc/p/test>

Notably 1000 0000 0001 rol 1 is 0000 0000 0011, but
back-end returned 2 (0000 0000 0010).

What we do to back-end is:
--------------------------------------------------------------------------
diff -x rts -x test -x doc -u p.20030507/predef.c p/predef.c
--- p.20030507/predef.c Fri May  2 13:40:33 2003
+++ p/predef.c  Tue Jun 17 18:19:29 2003
@@ -1693,6 +1693,39 @@
       }
     break;

+  case p_RotateLeft:
+  case p_RotateRight:
+  {
+    tree tmpval = NULL_TREE;
+    unsigned rotate_and_mask;
+
+    if (code == REAL_TYPE)
+      error ("argument 2 of `%s' must be of integer type", r_name);
+    else if (code2 == REAL_TYPE)
+      error ("argument 2 of `%s' must be of integer type", r_name);
+    if (length == 1)
+      val2 = integer_one_node;
+
+#if 0
+    switch (TYPE_PRECISION (type)) {
+        case 2: rotate_and_mask = 0x01; break;
+        case 4: rotate_and_mask = 0x03; break;
+        case 8: rotate_and_mask = 0x07; break;
+       case 16: rotate_and_mask = 0x0f; break;
+       case 32: rotate_and_mask = 0x1f; break;
+       case 64: rotate_and_mask = 0x3f; break;
+       default:
+          rotate_and_mask = 0;
+    }
+    if (rotate_and_mask)
+      tmpval = build_binary_op (BIT_AND_EXPR, val2, build_int_2
((unsigned)rotate_and_mask, 0), 0);
+    else
+#endif
+      tmpval = build_binary_op (TRUNC_MOD_EXPR, val2, build_int_2
((unsigned)TYPE_PRECISION (type), 0), 0);
+    retval = convert (type, build_binary_op ((r_num == p_RotateLeft) ?
LROTATE_EXPR : RROTATE_EXPR, val, tmpval, 0));
+  }
+    break;
+
   case p_FillChar:
     if (code3 != CHAR_TYPE)
       chk_dialect_1 ("non-`Char' values for argument 3 to `%s' are",
B_D_PASCAL, r_name);
diff -x rts -x test -x doc -u p.20030507/predef.h p/predef.h
--- p.20030507/predef.h Fri May  2 13:32:49 2003
+++ p/predef.h  Tue Jun 17 17:02:08 2003
@@ -292,6 +292,8 @@
 PREDEF_ROUTINE (Dec,                "-V,r|",         0,             B_D_M_PASCAL)
 PREDEF_ROUTINE (Succ,               "xv,r|",         ER_CONST,      ANY_PASCAL)
 PREDEF_ROUTINE (Pred,               "xv,r|",         ER_CONST,      ANY_PASCAL)
+PREDEF_ROUTINE (RotateLeft,         "xv,r|",          ER_CONST,     GNU_PASCAL)
+PREDEF_ROUTINE (RotateRight,        "xv,r|",          ER_CONST,     GNU_PASCAL)
 PREDEF_ROUTINE (Max,                "xww|",          ER_CONST,      GNU_PASCAL)
 PREDEF_ROUTINE (Min,                "xww|",          ER_CONST,      GNU_PASCAL)
 PREDEF_ROUTINE (Odd,                "bi|",           ER_CONST,      ANY_PASCAL)
-------------------------------------------------------------------------------



More information about the Gcc-bugs mailing list