[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