[LLVMdev] Apparent optimizer bug on X86_64
Csaba Raduly
rcsaba at gmail.com
Sat Mar 19 01:44:05 PDT 2011
Compiling a simple automaton created by GNU bison with -O1 or -O2
resulted in the following machine code:
1300 /*-----------------------------.
1301 | yyreduce -- Do a reduction. |
1302 `-----------------------------*/
1303 yyreduce:
1304 /* yyn is the number of a rule to reduce with. */
1305 yylen = yyr2[yyn];
0x0000000000400c14 <rpcalc_parse+628>: mov r15d,r14d
0x0000000000400c17 <rpcalc_parse+631>: movzx r12d,BYTE PTR
[r15+0x4015e2]
0x0000000000400c1f <rpcalc_parse+639>: mov eax,0x1
0x0000000000400c24 <rpcalc_parse+644>: mov r13,rax
0x0000000000400c27 <rpcalc_parse+647>: sub r13,r12
0x0000000000400c2a <rpcalc_parse+650>: mov eax,r13d //
assignment to zero-extends into rax
1306
1307 /* If YYLEN is nonzero, implement the default value of the action:
1308 `$$ = $1'.
1309
1310 Otherwise, the following line sets YYVAL to garbage.
1311 This behavior is undocumented and Bison
1312 users should not rely upon it. Assigning to YYVAL
1313 unconditionally makes the parser a bit smaller, and it avoids a
1314 GCC warning that YYVAL may be used uninitialized. */
1315 yyval = yyvsp[1-yylen];
=> 0x0000000000400c2d <rpcalc_parse+653>: movsd xmm0,QWORD PTR
[rbx+rax*8]
0x0000000000400c32 <rpcalc_parse+658>: movsd QWORD PTR
[rbp-0x808],xmm0
As far as I understand it, assigning to eax zero-extends to rax.
However, eax holds the result of "1-yylen" which is expected to be
negative, so it should be sign-extended before using its value as rax.
Indexing "in the wrong direction" causes a segfault at the instruction
indicated by '=>'
Here's the disassembly from -O0, which does a sign extension (movsxd):
1300 /*-----------------------------.
1301 | yyreduce -- Do a reduction. |
1302 `-----------------------------*/
1303 yyreduce:
1304 /* yyn is the number of a rule to reduce with. */
1305 yylen = yyr2[yyn];
0x0000000000401069 <+1945>: movsxd rax,DWORD PTR [rbp-0x80c]
0x0000000000401070 <+1952>: movzx ecx,BYTE PTR [rax*1+0x401f0f]
0x0000000000401078 <+1960>: mov DWORD PTR [rbp-0x824],ecx
0x000000000040107e <+1966>: mov ecx,0x1
1306
1307 /* If YYLEN is nonzero, implement the default value of the action:
1308 `$$ = $1'.
1309
1310 Otherwise, the following line sets YYVAL to garbage.
1311 This behavior is undocumented and Bison
1312 users should not rely upon it. Assigning to YYVAL
1313 unconditionally makes the parser a bit smaller, and it avoids a
1314 GCC warning that YYVAL may be used uninitialized. */
1315 yyval = yyvsp[1-yylen];
0x0000000000401083 <+1971>: sub ecx,DWORD PTR [rbp-0x824]
0x0000000000401089 <+1977>: movsxd rax,ecx
0x000000000040108c <+1980>: mov rdx,QWORD PTR [rbp-0x800]
0x0000000000401093 <+1987>: movsd xmm0,QWORD PTR [rdx+rax*8]
0x0000000000401098 <+1992>: movsd QWORD PTR [rbp-0x820],xmm0
yylen is of type YYSIZE_T, which is a macro that expands to size_t or
'unsigned int'. Perhaps clang/LLVM considers "1-yylen" to be unsigned?
Am I completely off-base?
This is
clang version 3.0 (trunk 127463)
Target: x86_64-unknown-linux-gnu
Thread model: posix
Csaba
--
GCS a+ e++ d- C++ ULS$ L+$ !E- W++ P+++$ w++$ tv+ b++ DI D++ 5++
The Tao of math: The numbers you can count are not the real numbers.
Life is complex, with real and imaginary parts.
"Ok, it boots. Which means it must be bug-free and perfect. " -- Linus Torvalds
"People disagree with me. I just ignore them." -- Linus Torvalds
More information about the llvm-dev
mailing list