hans added a comment.

> $ bin/clang -m32 -O0 /tmp/a.c && ./a.out
> -nan
> 
>   Before your change, it prints 3.140000.

I looked through the Intel manual to understand what's happening in detail:

When we return from f() with the new ABI, we write to the %mm0 register, and as 
a side effect:

(9.5.1) After each MMX instruction, the entire x87 FPU tag word is set to valid 
(00B).

What does that mean?

(8.1.7) "The x87 FPU uses the tag values to detect stack overflow and underflow 
conditions (see Section 8.5.1.1)"

(8.5.1.1) "Stack overflow — An instruction attempts to load a non-empty x87 FPU 
register from memory. A non-empty
register is defined as a register containing a zero (tag value of 01), a valid 
value (tag value of 00), or a special
value (tag value of 10).

When the x87 FPU detects stack overflow or underflow, it sets the IE flag (bit 
0) and the SF flag (bit 6) in the x87
FPU status word to 1. It then sets condition-code flag C1 (bit 9) in the x87 
FPU status word to 1 if stack overflow
occurred or to 0 if stack underflow occurred.
If the invalid-operation exception is masked, the x87 FPU returns the floating 
point, integer, or packed decimal
integer indefinite value to the destination operand, depending on the 
instruction being executed. This value over-
writes the destination register or memory location specified by the 
instruction."

Okay, so essentially any MMX instruction marks the x87 register stack as full, 
and when we try to store into it in d() with "fldl" we get a stack overflow, 
and because the exception is masked, it stores "the floating point indefinite 
value" into the register, which is what we end up printing.

At least I finally think I understand what's going on :-)


Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D59744/new/

https://reviews.llvm.org/D59744



_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to