Caveat: This may not be a complete answer as to why, but here's some data based on compiling with various options and disassembling the output ...
The second program [using only literal constants] does not generate any floating point instructions. It does a single printf
. (i.e. all calculations are done within the compiler).
So, the following is limited to the first program.
You didn't specify what [other] command line options you gave to gcc
, but I imagine only -ansi
.
I've got a 64 bit linux machine [with gcc
5.3.1], so I had to add -m32
.
Without that, the disassembly [for 64 bit], with or without -ansi
is the same and produces Unequal
[It uses the XMM
instructions]. With -O2
, no floating point instructions are generated, just a printf
[with or without -ansi
]. Again, the same.
If I use -m32
and -O2
, only the printf
is generated and the output is Unequal
, regardless of -ansi
or not
The only disparity occurs between 32 bit, optimization off, and use of -ansi
or not. Here, gcc
generates instructions for the older/traditional 387 FP coprocessor unit.
Without -ansi
, here is the disassembly:
dyn.o: file format elf32-i386
Disassembly of section .text:
00000000 <main>:
0: 8d 4c 24 04 lea 0x4(%esp),%ecx
4: 83 e4 f0 and $0xfffffff0,%esp
7: ff 71 fc pushl -0x4(%ecx)
a: 55 push %ebp
b: 89 e5 mov %esp,%ebp
d: 51 push %ecx
e: 83 ec 14 sub $0x14,%esp
11: dd 05 10 00 00 00 fldl 0x10
17: dd 5d f0 fstpl -0x10(%ebp)
1a: dd 05 18 00 00 00 fldl 0x18
20: dd 5d e8 fstpl -0x18(%ebp)
23: dd 45 f0 fldl -0x10(%ebp)
26: dd 45 e8 fldl -0x18(%ebp)
29: df e9 fucomip %st(1),%st
2b: dd d8 fstp %st(0)
2d: 7a 1e jp 4d <L00>
2f: dd 45 f0 fldl -0x10(%ebp)
32: dd 45 e8 fldl -0x18(%ebp)
35: df e9 fucomip %st(1),%st
37: dd d8 fstp %st(0)
39: 75 12 jne 4d <L00>
3b: 83 ec 0c sub $0xc,%esp
3e: 68 00 00 00 00 push $0x0
43: e8 fc ff ff ff call 44 <main+0x44>
48: 83 c4 10 add $0x10,%esp
4b: eb 10 jmp 5d <L01>
4d:L00 83 ec 0c sub $0xc,%esp
50: 68 06 00 00 00 push $0x6
55: e8 fc ff ff ff call 56 <main+0x56>
5a: 83 c4 10 add $0x10,%esp
5d:L01 b8 00 00 00 00 mov $0x0,%eax
62: 8b 4d fc mov -0x4(%ebp),%ecx
65: c9 leave
66: 8d 61 fc lea -0x4(%ecx),%esp
69: c3 ret
With -ansi
, it is the same except for a single instruction:
--- dynstd.dis 2016-06-09 09:58:18.719906988 -0700
+++ dynansi.dis 2016-06-09 09:58:44.266286688 -0700
@@ -14,7 +14,7 @@
e: 83 ec 14 sub $0x14,%esp
11: dd 05 10 00 00 00 fldl 0x10
17: dd 5d f0 fstpl -0x10(%ebp)
- 1a: dd 05 18 00 00 00 fldl 0x18
+ 1a: dd 05 10 00 00 00 fldl 0x10
20: dd 5d e8 fstpl -0x18(%ebp)
23: dd 45 f0 fldl -0x10(%ebp)
26: dd 45 e8 fldl -0x18(%ebp)
Notice that slightly above the difference there is an fldl 0x10
. Then, without -ansi
, it is followed by fldl 0x18
. With -ansi
, it is followed by fldl 0x10
. So, without -ansi
[my best guess is] we are comparing 0x10 == 0x18
[Unequal] and with -ansi
we are comparing 0x10 == 0x10
[Equal]
Almost as a side note, I repeated the same tests with clang
, but even with -m32
, it generates XMM
instructions, the disassembly is the same, and the output is always Unequal
.
So, AFAICT, this may be a code generation issue (i.e. bug) with gcc
for one limited set of options.