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