Bug #60057 sel_arg_range_seq_next loops, optimized compilation/VS2010
Submitted: 9 Feb 2011 18:29 Modified: 31 Jul 2012 19:45
Reporter: Vladislav Vaintroub Email Updates:
Status: Not a Bug Impact on me:
None 
Category:MySQL Server Severity:S3 (Non-critical)
Version:5.6.2, 5.6.7, 5.7.0 OS:Windows
Assigned to: CPU Architecture:Any
Tags: Contribution

[9 Feb 2011 18:29] Vladislav Vaintroub
Description:
If server is compiled with Visual Studio 2010 in optimized configuration
(RelwithDebInfo), mysqld loops inside sel_arg_range_seq_next() function during
main.lowercase_table_grant test.

This looks like compiler backend error. Debug works fine, if this function is excluded from optimization with pragma, test will also pass ok.

The loop that does not end is this one

  /* Ok, can't step down, walk left until we can step down */
  while (1)
  {
    if (seq->i == 1) // can't step left
      return 1;
....

How to repeat:
compile mysql server with VS2010 like this

mkdir xxx
cd xxx
cmake .. -G "Visual Studio 2010"
devenv mysql.sln /build relwithdebinfo

cd mysql-test
perl mysql-test-run.pl lowercase_table_grant

Suggested fix:
Simplify function:)

Disabling global optimization on the affected function with "pragma optimize" fixes the issue.

=== modified file 'sql/opt_range.cc'
--- sql/opt_range.cc	2010-12-29 00:38:59 +0000
+++ sql/opt_range.cc	2011-02-09 18:18:30 +0000
@@ -7607,7 +7607,9 @@
     0  Ok
     1  No more ranges in the sequence
 */
-
+#if defined (_MSC_VER)
+#pragma optimize("g", off)
+#endif
 //psergey-merge-todo: support check_quick_keys:max_keypart
 uint sel_arg_range_seq_next(range_seq_t rseq, KEY_MULTI_RANGE *range)
 {
@@ -7767,6 +7769,9 @@
   return 0;
 }
 
+#if defined (_MSC_VER)
+#pragma optimize("g", on)
+#endif
 
 /*
   Calculate estimate of number records that will be retrieved by a range
[9 Feb 2011 18:30] Vladislav Vaintroub
Both 32 and 64 bit are affected
[24 Mar 2011 13:18] Santo Leto
Hi,
Thank you for a problem report.

I am not able to repeat this bug with version 5.6.3:

cmake ..\..\mysql-source\mysql-trunk -G "Visual Studio 10" -DBUILD_CONFIG=mysql_release -DSIGNCODE=0
-- Check for working C compiler using: Visual Studio 10
-- Check for working C compiler using: Visual Studio 10 -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler using: Visual Studio 10
-- Check for working CXX compiler using: Visual Studio 10 -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Looking for sys/types.h
-- Looking for sys/types.h - found
-- Looking for stdint.h
-- Looking for stdint.h - found
-- Looking for stddef.h
-- Looking for stddef.h - found
-- Check size of void *
-- Check size of void * - done
-- MySQL 5.6.3-m5
-- Looking for include files CMAKE_HAVE_PTHREAD_H
-- Looking for include files CMAKE_HAVE_PTHREAD_H - not found.
-- Found Threads: TRUE
-- Check size of time_t
-- Check size of time_t - done
-- Performing Test TIME_T_UNSIGNED
-- Performing Test TIME_T_UNSIGNED - Failed
-- Googletest was not found. gtest-based unit tests will be disabled. You can run cmake . -DENABLE_DOWNLOADS=1 to automatically download and build required components from source.
-- Configuring done
-- Generating done
-- Build files have been written to: D:/Santo_Local/mysql-builds/mysql-trunk-ofs-03242011

vcexpress MySql.sln /build RelWithDebInfo /project package /out compilation_output.txt

[...]
110>  CPack: Package D:/Santo_Local/mysql-builds/mysql-trunk-ofs-03242011/mysql-5.6.3-m5-win32.zip generated.
========== Build: 110 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

cd mysql-test

perl mysql-test-run.pl lowercase_table_grant
Logging: D:/Santo_Local/mysql-source/mysql-trunk/mysql-test/mysql-test-run.pl  lowercase_table_grant
110324 13:56:27 [Note] Plugin 'FEDERATED' is disabled.
110324 13:56:27 [Note] Binlog end
110324 13:56:27 [Note] Shutting down plugin 'MyISAM'
110324 13:56:27 [Note] Shutting down plugin 'CSV'
MySQL Version 5.6.3
Checking supported features...
 - skipping ndbcluster
 - SSL connections supported
Collecting tests...
vardir: D:/Santo_Local/mysql-builds/mysql-trunk-ofs-03242011/mysql-test/var
Removing old var directory...
Creating var directory 'D:/Santo_Local/mysql-builds/mysql-trunk-ofs-03242011/mysql-test/var'...
Installing system database...
Using server port 59486

==============================================================================

TEST                                      RESULT   TIME (ms) or COMMENT
--------------------------------------------------------------------------

worker[1] Using MTR_BUILD_THREAD 300, with reserved ports 13000..13009
main.lowercase_table_grant               [ pass ]   1217
--------------------------------------------------------------------------
The servers were restarted 0 times
Spent 1.217 of 52 seconds executing testcases

Completed: All 1 tests were successful.
[31 Jul 2012 19:32] MySQL Verification Team
FYI this bug is still repeatable on VS 2010 Premium today in 5.6.7 and 5.7.0.  I will post details shortly. I suspect a compiler bug.
[31 Jul 2012 19:45] MySQL Verification Team
Decompiled optimized version of sel_arg_range_seq_next:

--------------------------------
The loop from working build from VS 2010SP1 Professional
--------------------------------
:005DD450 loc_5DD450:         ; CODE XREF: sel_arg_range_seq_next+77
:005DD450            mov     eax, [esi+1D0h]
:005DD456            cmp     eax, 1
:005DD459            jz      loc_5DD872
:005DD45F            dec     eax
:005DD460            lea     edx, ds:0[eax*8]
:005DD467            sub     edx, eax
:005DD469            mov     [esi+1D0h], eax
:005DD46F            mov     eax, [esi+edx*4+28h]
:005DD473            cmp     dword ptr [eax+20h], 0
:005DD477            jz      short loc_5DD450
:005DD479
:005DD479 loc_5DD479:        ; CODE XREF: sel_arg_range_seq_next+48

--------------------------------
The loop from buggy build from VS 2010 premium:
------------------------------
:005DD450 loc_5DD450:       ; CODE XREF: sel_arg_range_seq_next+73
:005DD450            cmp     ecx, 1
:005DD453            jz      loc_5DD86C
:005DD459            lea     eax, [ecx-1]
:005DD45C            lea     edx, ds:0[eax*8]
:005DD463            sub     edx, eax
:005DD465            mov     [edi+1D0h], eax
:005DD46B            mov     eax, [edi+edx*4+28h]
:005DD46F            cmp     dword ptr [eax+20h], 0
:005DD473            jz      short loc_5DD450
:005DD475
:005DD475 loc_5DD475:      ; CODE XREF: sel_arg_range_seq_next+48

Notice how the ecx register (aka seq->curr_kp--) never changes in the buggy build!  You can test the faulty build vs the working build with the following testcase:

drop table if exists `t1`;
create table `t1`(`a` date not null,`b` int,key(`b`,`a`))engine=innodb;
insert into t1 values ('2012-01-01',1),('2001-09-01',2);
select 1 from `t1` inner join `t1` `a` 
on `t1`.`a` is null where  `t1`.`b` is
null;

So, application of visual studio service pack seems to have fixed it.