http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52408
Bug #: 52408
Summary: Incorrect assembler generated for zvdep_imm64
Classification: Unclassified
Product: gcc
Version: 4.6.2
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: target
AssignedTo: [email protected]
ReportedBy: [email protected]
Host: hppa64-*-*
Target: hppa64-*-*
Build: hppa64-*-*
The following testcase is miscompiled at -O1:
typedef unsigned long long loff_t;
typedef unsigned long long blkcnt_t;
typedef unsigned long long u64;
#define MAX_LFS_FILESIZE 0x7fffffffffffffffULL
loff_t ext4_max_size(int blkbits, int has_huge_files)
{
loff_t res;
loff_t upper_limit = MAX_LFS_FILESIZE;
if (!has_huge_files || sizeof(blkcnt_t) < sizeof(u64)) {
upper_limit = (1LL << 32) - 1;
upper_limit >>= (blkbits - 9);
upper_limit <<= blkbits;
}
res = (1LL << 32) - 1;
res <<= blkbits;
if (res > upper_limit)
res = upper_limit;
return res;
}
int main(void)
{
printf("res = 0x%lx\n", ext4_max_size(12, 0));
return 0;
}
Wrong code is generated for the "res <<= blkbits;" operation.
We have the following rtl:
(insn 27 26 65 (set (reg/v:DI 31 %r31 [orig:71 res ] [71])
(ashift:DI (const_int 4294967295 [0xffffffff])
(minus:DI (const_int 63 [0x3f])
(reg:DI 60 SAR [82])))) ext4.c:21 230 {zvdep_imm64}
(expr_list:REG_DEAD (reg:DI 60 SAR [82])
(expr_list:REG_EQUAL (ashift:DI (const_int 4294967295 [0xffffffff])
(reg/v:DI 31 %r31 [orig:75 blkbits+-4 ] [75]))
(nil))))
The pattern for zvdep_imm64 is:
(define_insn "zvdep_imm64"
[(set (match_operand:DI 0 "register_operand" "=r")
(ashift:DI (match_operand:DI 1 "lhs_lshift_cint_operand" "")
(minus:DI (const_int 63)
(match_operand:DI 2 "register_operand" "q"))))]
"TARGET_64BIT"
"*
{
int x = INTVAL (operands[1]);
operands[2] = GEN_INT (4 + exact_log2 ((x >> 4) + 1));
operands[1] = GEN_INT ((x & 0x1f) - 0x20);
return \"depdi,z %1,%%sar,%2,%0\";
}"
[(set_attr "type" "shift")
(set_attr "length" "4")])
The lhs_lshift_cint_operand predicate allows the unsigned long long
value 0xffffffff, but it is truncated when assigned to x. As a result,
the call to exact_log2 fails and returns -1. This results in the following
incorrect instruction:
depdi,z -1,%sar,3,%r31
There appear to be a few more instances with the same problem...
The problem has been present for years and affects all active versions.