Hello,
My GCC porting for our own VLIW processor tracks mainline weekly. Test
991118-1.c has failed since two weeks ago. Following is a simplified version
of 99118-1.c. After some investigation, I found the following statement is
expanded to RTL wrongly.
;; tmp2.field = (<unnamed-signed:52>) (<unnamed-signed:52>) ((long long int)
tmp2.field ^ 0x8765412345678);
(insn 9 8 10
/projects/firepath/tools/work/bmei/gcc-head/src/gcc/testsuite/gcc.c-torture/execute/991118-1.c:23
(set (reg/f:SI 88)
(symbol_ref:SI ("tmp2") [flags 0x2] <var_decl 0xf7fb8170 tmp2>)) -1
(nil))
(insn 10 9 11
/projects/firepath/tools/work/bmei/gcc-head/src/gcc/testsuite/gcc.c-torture/execute/991118-1.c:23
(set (reg:DI 89)
(mem/s/j/c:DI (reg/f:SI 88) [0+0 S8 A64])) -1 (nil))
(insn 11 10 12
/projects/firepath/tools/work/bmei/gcc-head/src/gcc/testsuite/gcc.c-torture/execute/991118-1.c:23
(set:DI (reg:DI 90)
(const_int 284280 [0x45678])) -1 (nil)) <---- wrong constant
(insn 12 11 13
/projects/firepath/tools/work/bmei/gcc-head/src/gcc/testsuite/gcc.c-torture/execute/991118-1.c:23
(set (reg:DI 91)
(xor:DI (reg:DI 89)
(reg:DI 90))) -1 (nil))
(insn 13 12 0
/projects/firepath/tools/work/bmei/gcc-head/src/gcc/testsuite/gcc.c-torture/execute/991118-1.c:23
(set (mem/s/j/c:DI (reg/f:SI 88) [0+0 S8 A64])
(reg:DI 91)) -1 (nil))
Insn 11 only preserves the lower 20-bit of the 52-bit long constant. Further
investigation shows the problem arises in
optimize_bitfield_assignment_op function (expr.c).
...
case BIT_XOR_EXPR:
if (TREE_CODE (op1) != INTEGER_CST)
break;
value = expand_expr (op1, NULL_RTX, GET_MODE (str_rtx), EXPAND_NORMAL);
value = convert_modes (GET_MODE (str_rtx),
TYPE_MODE (TREE_TYPE (op1)), value,
TYPE_UNSIGNED (TREE_TYPE (op1)));
/* We may be accessing data outside the field, which means
we can alias adjacent data. */
if (MEM_P (str_rtx))
{
str_rtx = shallow_copy_rtx (str_rtx);
set_mem_alias_set (str_rtx, 0);
set_mem_expr (str_rtx, 0);
}
binop = TREE_CODE (src) == BIT_IOR_EXPR ? ior_optab : xor_optab;
if (bitpos + bitsize != GET_MODE_BITSIZE (GET_MODE (str_rtx)))
{
rtx mask = GEN_INT (((unsigned HOST_WIDE_INT) 1 << bitsize)
<------------ Suspected bug
- 1);
value = expand_and (GET_MODE (str_rtx), value, mask,
NULL_RTX);
}
value = expand_shift (LSHIFT_EXPR, GET_MODE (str_rtx), value,
build_int_cst (NULL_TREE, bitpos),
NULL_RTX, 1);
result = expand_binop (GET_MODE (str_rtx), binop, str_rtx,
value, str_rtx, 1, OPTAB_WIDEN);
Here the bitpos = 0, bitsize = 52. HOST_WIDE_INT for our processor is 32,
though 64-bit long long type is supported. The marked statement produces a
mask of 0xfffff, thus causes the upper 32-bit removed later. Is this a
potential bug, or did I miss something?
I also tried the older version (> 2 weeks ago). This function is not called at
all, so can produce correct code.
Cheers,
Bingfeng
Broadcom UK