Hi,

Consider minimal reproduction code:

#include "math.h"
#include "stdio.h"

double __attribute__ ((noinline))
slip(double a)
{
  return (cos(a) + sin(a));
}

int main(void)
{
  double a = 4.47460300787e+182;
  double slipped = slip(a);
  printf("slipped = %lf\n", slipped);
  return 0;
}

Compiling on
gcc (Ubuntu 4.4.3-4ubuntu5) 4.4.3

First on O0:

gcc -o sincos.64 sincos.c -O0 -lm
./sincos.64
slipped = -1.141385

That is correct.

Next on O1:

gcc -o sincos.64 sincos.c -O1 -lm
./sincos.64
slipped = -0.432436

That is obviously incorrect.

Lets dive inside: on O0:

slip:
.LFB0:
  .cfi_startproc
  pushq %rbp
  .cfi_def_cfa_offset 16
  movq  %rsp, %rbp
  .cfi_offset 6, -16
  .cfi_def_cfa_register 6
  subq  $16, %rsp
  movsd %xmm0, -8(%rbp)
  movsd -8(%rbp), %xmm0
  call  cos
  movsd %xmm0, -16(%rbp)
  movsd -8(%rbp), %xmm0
  call  sin
  addsd -16(%rbp), %xmm0
  leave
  ret

we have separate sin and cos calls, and everything works fine.

On O1:

slip:
.LFB25:
  .cfi_startproc
  subq  $24, %rsp
  .cfi_def_cfa_offset 32
  leaq  8(%rsp), %rdi
  movq  %rsp, %rsi
  call  sincos
  movsd 8(%rsp), %xmm0
  addsd (%rsp), %xmm0
  addq  $24, %rsp
  ret

Here we have one sincos call, and it works wrong.

Why gcc performs such buggy optimization, and may I switch it off
somehow? Or may be I don't understand something and problem is in my
code?

---
With best regards, Konstantin

Reply via email to