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

Reply via email to