Le 12/08/2015 13:09, Richard Biener a écrit :
On Wed, Aug 12, 2015 at 1:07 PM, Markus Trippelsdorf
<mar...@trippelsdorf.de> wrote:
On 2015.08.12 at 13:01 +0200, Richard Biener wrote:
What kind of error does ubsan run into?  That is, for which 'prec'?

See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67042

Ugh.  Stupid C.

My fear is that with so many stmts sext_hwi isn't any longer considered for
inlining, even if prec is constant.  What's the generated code for its
out-of line
copy with/without the patch?


The difference on x86_64 is:

        .cfi_startproc
        cmpl    $64, %esi
        je      .L3
-       movl    $64, %ecx
-       subl    %esi, %ecx
-       salq    %cl, %rdi
+       leal    -1(%rsi), %ecx
+       movl    $1, %eax
+       movq    %rax, %rdx
+       salq    %cl, %rdx
+       movl    %esi, %ecx
+       salq    %cl, %rax
+       subq    $1, %rax
+       andq    %rax, %rdi
+       xorq    %rdx, %rdi
        movq    %rdi, %rax
-       sarq    %cl, %rax
+       subq    %rdx, %rax
        ret
        .p2align 4,,10
        .p2align 3

with -O2, tests attached.
Yes it's worse. I thought it was better to avoid undefined behaviour at all prices to avoid "bad surprises".

Mikael




typedef signed long long HOST_WIDE_INT;

#define HOST_BITS_PER_WIDE_INT (8 * sizeof(HOST_WIDE_INT))

#define HOST_WIDE_INT_C(X) X ## LL
#define HOST_WIDE_INT_UC(X) HOST_WIDE_INT_C (X ## U)
#define HOST_WIDE_INT_1 HOST_WIDE_INT_C (1)
#define HOST_WIDE_INT_1U HOST_WIDE_INT_UC (1)
#define HOST_WIDE_INT_M1 HOST_WIDE_INT_C (-1)
#define HOST_WIDE_INT_M1U HOST_WIDE_INT_UC (-1)

#define gcc_checking_assert(test)

HOST_WIDE_INT
sext_hwi (HOST_WIDE_INT src, unsigned int prec)
{
  if (prec == HOST_BITS_PER_WIDE_INT)
    return src;
  else
    {
      gcc_checking_assert (prec < HOST_BITS_PER_WIDE_INT);
      int shift = HOST_BITS_PER_WIDE_INT - prec;
      return (src << shift) >> shift;
    }
}




typedef signed long long HOST_WIDE_INT;

#define HOST_BITS_PER_WIDE_INT (8 * sizeof(HOST_WIDE_INT))

#define HOST_WIDE_INT_C(X) X ## LL
#define HOST_WIDE_INT_UC(X) HOST_WIDE_INT_C (X ## U)
#define HOST_WIDE_INT_1 HOST_WIDE_INT_C (1)
#define HOST_WIDE_INT_1U HOST_WIDE_INT_UC (1)
#define HOST_WIDE_INT_M1 HOST_WIDE_INT_C (-1)
#define HOST_WIDE_INT_M1U HOST_WIDE_INT_UC (-1)

#define gcc_checking_assert(test)

HOST_WIDE_INT
sext_hwi (HOST_WIDE_INT src, unsigned int prec)
{
  if (prec == HOST_BITS_PER_WIDE_INT)
    return src;
  else
    {
      gcc_checking_assert (prec < HOST_BITS_PER_WIDE_INT);
      HOST_WIDE_INT sign_mask = HOST_WIDE_INT_1 << (prec - 1);
      HOST_WIDE_INT value_mask = (HOST_WIDE_INT_1U << prec) - HOST_WIDE_INT_1U;
      return (((src & value_mask) ^ sign_mask) - sign_mask);
    }
}



Reply via email to