http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55142



--- Comment #24 from Eric Botcazou <ebotcazou at gcc dot gnu.org> 2012-11-08 
16:11:25 UTC ---

> I applied i386 change at

> 

> http://gcc.gnu.org/bugzilla/attachment.cgi?id=28591

> 

> to compile it:

> 

> [hjl@gnu-tools-1 tmp]$ /export/build/gnu/gcc/release/usr/gcc-4.8.0/bin/gcc

> -mtune=generic -march=x86-64 -maddress-mode=long -mx32 -O2 -fPIC rtld.c

> -std=gnu99 -fgnu89-inline  -S

> [hjl@gnu-tools-1 tmp]$  egrep ", -[0-9]*\(%rax" rtld.s 

>     movl    %ecx, -1073743664(%rax)

>     movl    %ecx, -1073742592(%rax)

>     movl    %edx, -1073743664(%rax)

>     movl    %edx, -1073742592(%rax)

> [hjl@gnu-tools-1 tmp]$ 

> 

> All those stores should be zero-extended.



OK, thanks.  Everything is correctly zero-extended until:



    case PLUS:

    case MULT:

      /* FIXME: For addition, we used to permute the conversion and

     addition operation only if one operand is a constant and

     converting the constant does not change it or if one operand

     is a constant and we are using a ptr_extend instruction

     (POINTERS_EXTEND_UNSIGNED < 0) even if the resulting address

     may overflow/underflow.  We relax the condition to include

     zero-extend (POINTERS_EXTEND_UNSIGNED > 0) since the other

     parts of the compiler depend on it.  See PR 49721.



     We can always safely permute them if we are making the address

     narrower.  */

      if (GET_MODE_SIZE (to_mode) < GET_MODE_SIZE (from_mode)

      || (GET_CODE (x) == PLUS

          && CONST_INT_P (XEXP (x, 1))

          && (POINTERS_EXTEND_UNSIGNED != 0

          || XEXP (x, 1) == convert_memory_address_addr_space

                      (to_mode, XEXP (x, 1), as))))

    return gen_rtx_fmt_ee (GET_CODE (x), to_mode,

                   convert_memory_address_addr_space

                 (to_mode, XEXP (x, 0), as),

                   XEXP (x, 1));

      break;



It's clear that the distribution is invalid, whatever POINTERS_EXTEND_UNSIGNED

is defined to.  It becomes valid only under conditions of non-overflow that

depend upon the value of POINTERS_EXTEND_UNSIGNED, as stated in the head

comment of the function.



If POINTERS_EXTEND_UNSIGNED, it's valid if there is no overflow in the address.



If POINTERS_EXTEND_UNSIGNED > 0, it's valid if either the constant is positive

(and there is no overflow in the address) or the constant is negative and the

variable part is sufficiently large.  The condition aren't fulfilled here since

the constant is very large negative and the variable part small.



I think the most robust solution would be to always zero-extend the addresses

for -mx32, i.e. output

  movl    %ecx, -1073743664(%eax)

even if the address is a PLUS in DImode.  Otherwise, we're left with kludges...

Reply via email to