Adding a new thread model to GCC

2016-04-13 Thread lh_mouse
Hi all,

The 'win32' thread model of gcc has been there since long long ago, being 
compatible with very old Windows versions, also having a number of drawbacks:
  0) its implementation is very inefficient, and
  1) its mutexes and condition variables require dynamic initialization and are 
unusable in C++11 as std::mutex requires a `constexpr` constructor, and
  2) allocating a number of rarely used mutexes or condition variables would 
eventually make the system run out of kernel objects.

As a solution for 1) and 2), Microsoft introduced keyed events, details of 
which can be found here:
http://joeduffyblog.com/2006/11/28/windows-keyed-events-critical-sections-and-new-vista-synchronization-features/

In one word: the Windows SRWLOCK and CONDITION_VARIABLE have been introduced 
since Vista and are working well without any dynamic initialization, just like 
FUTEX.
But there are still some major drawbacks:
  0) the SRWLOCK can be used as an exclusive mutex but it does not have an 
equivalent function to pthread_mutex_timedwait, and 
  1) the CONDITION_VARIABLE can only be used with SRWLOCK and CRITICAL_SECTION 
and no user-defined mutexes can be supportd.

As a solution, I come up with my own library: 
https://github.com/lhmouse/mcfgthread
With 4 threads contending my mutex implementation turns to be 10 times faster 
than the gthr-win32 implementation on my Xeon E3-1230 v3 processor.
I have also done some research on gthr.h and successfully created a wrapper for 
__gthread_* functhins, which can be found in mcfgthread/src/env/gthread.h.

I am currently looking for ways to integrate this library into gcc as a new 
thread model, let's say 'nt6' for example, so GCC can be configured with 
--enable-threads=nt6.
But there is so little documentation about that. If someone know how to add a 
new thread model in GCC, I would appreciate that.

Also, this library has not been fully tested. If someone has interest in 
exploring how it works or testing it, I might be able to help.

--
Best regards,
lh_mouse
2016-04-13



Re: Re: Adding a new thread model to GCC

2016-04-13 Thread lh_mouse
Thanks for your reply. :>

However I am still having problems building GCC. (Yesterday stage 1 was ok, but 
during stage 2 autoconf just failed to find any standard headers. I am still 
struggling with it.)
Once I build gcc successfully I will have a look at that configure.ac. Wish me 
luck. (btw this could be one or two days later. :<)

--   
Best regards,
lh_mouse
2016-04-13

-
发件人:Jonathan Wakely 
发送日期:2016-04-13 18:30
收件人:lh_mouse
抄送:gcc,mingw-w64-public
主题:Re: Adding a new thread model to GCC

On 13 April 2016 at 10:17, lh_mouse wrote:
> Hi all,
>
> The 'win32' thread model of gcc has been there since long long ago, being 
> compatible with very old Windows versions, also having a number of drawbacks:
>   0) its implementation is very inefficient, and
>   1) its mutexes and condition variables require dynamic initialization and 
> are unusable in C++11 as std::mutex requires a `constexpr` constructor, and
>   2) allocating a number of rarely used mutexes or condition variables would 
> eventually make the system run out of kernel objects.
>
> As a solution for 1) and 2), Microsoft introduced keyed events, details of 
> which can be found here:
> http://joeduffyblog.com/2006/11/28/windows-keyed-events-critical-sections-and-new-vista-synchronization-features/
>
> In one word: the Windows SRWLOCK and CONDITION_VARIABLE have been introduced 
> since Vista and are working well without any dynamic initialization, just 
> like FUTEX.
> But there are still some major drawbacks:
>   0) the SRWLOCK can be used as an exclusive mutex but it does not have an 
> equivalent function to pthread_mutex_timedwait, and

Some of our supported targets don't support pthread_mutex_timedwait
either (at least Mac OS X and HP-UX) so we have code in libstdc++ to
support mutexes but not timed mutexes. That might also work for your
new model.

>   1) the CONDITION_VARIABLE can only be used with SRWLOCK and 
> CRITICAL_SECTION and no user-defined mutexes can be supportd.

That's OK, std::condition_variable only needs to work with std::mutex,
and then std::condition_variable_any (which works with user-defined
mutexes) only requires std::mutex and std::condition_variable. The
code to use user-defined mutexes is portable C++11, so doesn't need
any platform-specific code.

> As a solution, I come up with my own library: 
> https://github.com/lhmouse/mcfgthread
> With 4 threads contending my mutex implementation turns to be 10 times faster 
> than the gthr-win32 implementation on my Xeon E3-1230 v3 processor.
> I have also done some research on gthr.h and successfully created a wrapper 
> for __gthread_* functhins, which can be found in mcfgthread/src/env/gthread.h.

Great! I haven't looked at the code, but I've been hoping someone
would do something like this to improve the std::mutex and
std::condition_variable implementations for modern Windows systems.


> I am currently looking for ways to integrate this library into gcc as a new 
> thread model, let's say 'nt6' for example, so GCC can be configured with 
> --enable-threads=nt6.
> But there is so little documentation about that. If someone know how to add a 
> new thread model in GCC, I would appreciate that.

See line 1589 in gcc/configure.ac, where the allowed thread models are
defined. Your gthreads wrapper header should be added as
libgcc/config/i386/gthr-nt6.h and you might also need some changes to
libgcc/configure.ac (see how it handles the existing gthr-win32.h
model).

You will need to use autoconf to regenerate the configure files after
editing the configure.ac files (or for now you can just edit the
configure files by hand, but eventually changes must go into the
configure.ac files). I can probably help with that, although I can't
build or test anything on Windows.

Once you've added the new thread model as a gthr-xxx.h file in libgcc
there will also be some work needed in libstdc++ to detect and
correctly use the new model (e.g. to detect that the timedwait
functions are not supported, so that timed mutexes will be disabled).

We might want to discuss that latter part on the libstdc++ list.




Re: Re: Adding a new thread model to GCC

2016-04-13 Thread lh_mouse
Yes I learnt those *ByAddress* functions a few months ago and was shocked that 
Microsoft had plagiarized futex from Linux.
As you have pointed out already, those APIs are only available on  Windows 8 
and later.

If we need fuex semantics on Windows 7 and earlier, we must simulate it.
However, since futexes and keyed events work differently, simulation of futexes 
using keyed events would:
  0) require a lot of work, and
  1) suffer from performance penalty just like if we simulate keyed events on 
Windows 2000.

The major difference is that, the FUTEX_WAIT syscall is an atomic 
compare-and-sleep operation, while the NtWaitForKeyedEvent syscall provides no 
comparison.
Instead, the NtReleasedKeyedEvent syscall blocks the current thread until one 
thread is woken up, while FUTEX_WAKE does nothing and returns immediately.

So here is my condition: in no event shall portability harm either efficiency 
or maintainability.
Linux and Windows work differently. I consider it 'harmful' to make one look 
like the other.


--   
Best regards,
lh_mouse
2016-04-14

-
发件人:Torvald Riegel 
发送日期:2016-04-14 01:40
收件人:lh_mouse
抄送:gcc,mingw-w64-public
主题:Re: Adding a new thread model to GCC

On Wed, 2016-04-13 at 17:17 +0800, lh_mouse wrote:
> Hi all,
> 
> The 'win32' thread model of gcc has been there since long long ago, being 
> compatible with very old Windows versions, also having a number of drawbacks:
>   0) its implementation is very inefficient, and
>   1) its mutexes and condition variables require dynamic initialization and 
> are unusable in C++11 as std::mutex requires a `constexpr` constructor, and
>   2) allocating a number of rarely used mutexes or condition variables would 
> eventually make the system run out of kernel objects.
> 
> As a solution for 1) and 2), Microsoft introduced keyed events, details of 
> which can be found here:
> http://joeduffyblog.com/2006/11/28/windows-keyed-events-critical-sections-and-new-vista-synchronization-features/

Have you looked at WaitOnAddress and WakeByAddressSingle /
WakeByAddressAll too?  AFAIK this is new in Windows 8, and seems similar
to futexes.

I think it might be better to get a std::synchronic (or similar)
implementation into GCC, and then use these to implement at least the
mutexes:
https://github.com/ogiroux/synchronic/blob/master/include/synchronic

One benefit would be that we then have one place where we have optimized
spinning/blocking in libstdc++ on Windows, and less platform-specific
code.





Re: Re: Re: Adding a new thread model to GCC

2016-04-13 Thread lh_mouse
And don't forget that --enable-threads=win32 also enables emulated TLS, which 
is completely unnecessary if we have some kind of TLS support.

Because pthread_key_create() requires a destructor, TLS must still be emulated 
on x86 because there is no native support. The fiber local storage (FLS) APIs 
require the god damned __stdcall calling convention and are impossible to be 
made any use of.
On x64 __stdcall has no effect and FLS APIs can be used to implement TLS 
functions.

I tend to make a copy of the POSIX thread model and make some modification of 
it.

--   
Best regards,
lh_mouse
2016-04-14

-
发件人:Dongsheng Song 
发送日期:2016-04-14 11:02
收件人:lh_mouse
抄送:Torvald Riegel,gcc,mingw-w64-public
主题:Re: Re: Adding a new thread model to GCC

Currently, --enable-threads=win32 map to gthr-win32.{h|c}, could we map

--enable-threads=win32-vista
--enable-threads=win32-win7   // Windows 7 and Windows Server 2008 R2
--enable-threads=win32-win8   // Windows 8 and Windows Server 2012
--enable-threads=win32-win8.1 // Windows 8.1 and Windows Server 2012 R2
--enable-threads=win32-win10  // Windows 10 and Windows Server 2016

to gthr-windows.{h|c} with the corresponding _WIN32_WINNT macros ?

Regards,
Dongsheng

On Thu, Apr 14, 2016 at 10:24 AM, lh_mouse  wrote:
> Yes I learnt those *ByAddress* functions a few months ago and was shocked 
> that Microsoft had plagiarized futex from Linux.
> As you have pointed out already, those APIs are only available on  Windows 8 
> and later.
>
> If we need fuex semantics on Windows 7 and earlier, we must simulate it.
> However, since futexes and keyed events work differently, simulation of 
> futexes using keyed events would:
>   0) require a lot of work, and
>   1) suffer from performance penalty just like if we simulate keyed events on 
> Windows 2000.
>
> The major difference is that, the FUTEX_WAIT syscall is an atomic 
> compare-and-sleep operation, while the NtWaitForKeyedEvent syscall provides 
> no comparison.
> Instead, the NtReleasedKeyedEvent syscall blocks the current thread until one 
> thread is woken up, while FUTEX_WAKE does nothing and returns immediately.
>
> So here is my condition: in no event shall portability harm either efficiency 
> or maintainability.
> Linux and Windows work differently. I consider it 'harmful' to make one look 
> like the other.
>
>
> --
> Best regards,
> lh_mouse
> 2016-04-14
>
> -
> 发件人:Torvald Riegel 
> 发送日期:2016-04-14 01:40
> 收件人:lh_mouse
> 抄送:gcc,mingw-w64-public
> 主题:Re: Adding a new thread model to GCC
>
> On Wed, 2016-04-13 at 17:17 +0800, lh_mouse wrote:
>> Hi all,
>>
>> The 'win32' thread model of gcc has been there since long long ago, being 
>> compatible with very old Windows versions, also having a number of drawbacks:
>>   0) its implementation is very inefficient, and
>>   1) its mutexes and condition variables require dynamic initialization and 
>> are unusable in C++11 as std::mutex requires a `constexpr` constructor, and
>>   2) allocating a number of rarely used mutexes or condition variables would 
>> eventually make the system run out of kernel objects.
>>
>> As a solution for 1) and 2), Microsoft introduced keyed events, details of 
>> which can be found here:
>> http://joeduffyblog.com/2006/11/28/windows-keyed-events-critical-sections-and-new-vista-synchronization-features/
>
> Have you looked at WaitOnAddress and WakeByAddressSingle /
> WakeByAddressAll too?  AFAIK this is new in Windows 8, and seems similar
> to futexes.
>
> I think it might be better to get a std::synchronic (or similar)
> implementation into GCC, and then use these to implement at least the
> mutexes:
> https://github.com/ogiroux/synchronic/blob/master/include/synchronic
>
> One benefit would be that we then have one place where we have optimized
> spinning/blocking in libstdc++ on Windows, and less platform-specific
> code.
>
>
>




Re: Re: Adding a new thread model to GCC

2016-04-17 Thread lh_mouse
A glance over gthr.h reminds me __gthread_time_t. There seem few requirements 
documented in gthr.h.
I discussed this with Adrien Nader on mingw-w64's mailing list a few days ago.

Specifically, here are the two questions:
0) Should __gthread_time_t be a struct or a plain integral type?
The 'struct timespec' used by pthread is a struct introduced in POSIX.
However my implementation uses a plain uint64_t.
1) How to obtain a __gthread_time_t representing the current time?
According to Linux man pages, the timeout parameter of pthread_cond_timedwait() 
is the same as gettimeofday() - that is, it uses the wall clock.
My implementation uses GetTickCount64() - that is, my implementation uses a 
monotonic clock.

Quoting from ISO/IEC WG21 Draft N4582 (C++1z):
[quote]
30.4.1.3.1 Class timed_mutex [thread.timedmutex.class]
...
template 
bool try_lock_for(const chrono::duration& rel_time);
template 
bool try_lock_until(const chrono::time_point& abs_time);
...
[/quote]
the std::timed_mutex::try_lock_for() function template shall accept any clock 
type, hence we have to do timestamp translation. It is also important to know 
how libstdc++ handles this.

--   
Best regards,
lh_mouse
2016-04-18



Re: Re: Adding a new thread model to GCC

2016-04-18 Thread lh_mouse
I have added a thread model and added its corresponding header files. But it 
failed the linker.

The file 'gcc/libgcc/config/i386/t-mingw-pthread' which contained two lines:
  SHLIB_PTHREAD_CFLAG = -pthread
  SHLIB_PTHREAD_LDFLAG = -Wl,-lpthread

I copied the file to 'gcc/libgcc/config/i386/t-mingw-mcfgthread' and modified 
the two lines to:
  SHLIB_PTHREAD_CFLAG = -lmcfgthread
  SHLIB_PTHREAD_LDFLAG = -Wl,-lmcfgthread

It didn't work and I got a number of undefined references. The command line 
that invoked the linker didn't include either option.

How to solve this problem?

--   
Best regards,
lh_mouse
2016-04-18


9000-Added-mcf-thread-model-support-from-mcfgthread.patch
Description: Binary data


Re: Re: Re: Adding a new thread model to GCC

2016-04-18 Thread lh_mouse
Oh I missed the build-in specs in gcc/config/i386/mingw32.h and it was lack of 
-lmcfgthread in it that caused the failure. Stage 1 seemed ok.
Already hacked that. Rebuilding.

Apologize for that.

--   
Best regards,
lh_mouse
2016-04-18

-
发件人:Jonathan Wakely 
发送日期:2016-04-18 16:59
收件人:lh_mouse
抄送:gcc,mingw-w64-public
主题:Re: Re: Adding a new thread model to GCC

On 18 April 2016 at 08:39, lh_mouse wrote:
> I have added a thread model and added its corresponding header files. But it 
> failed the linker.
>
> The file 'gcc/libgcc/config/i386/t-mingw-pthread' which contained two lines:
>   SHLIB_PTHREAD_CFLAG = -pthread
>   SHLIB_PTHREAD_LDFLAG = -Wl,-lpthread
>
> I copied the file to 'gcc/libgcc/config/i386/t-mingw-mcfgthread' and modified 
> the two lines to:
>   SHLIB_PTHREAD_CFLAG = -lmcfgthread
>   SHLIB_PTHREAD_LDFLAG = -Wl,-lmcfgthread
>
> It didn't work and I got a number of undefined references. The command line 
> that invoked the linker didn't include either option.
>
> How to solve this problem?

What are the linker errors? When do they happen?




Re: Re: Re: Adding a new thread model to GCC

2016-04-18 Thread lh_mouse
> I don't see why it has to be a struct, it just has to be suitable as
> an argument to the relevant __gthread functions.

The type __gthread_time_t is referenced in 
gcc/libstdc++-v3/include/std/mutex:157
  __gthread_time_t __ts = {
static_cast(__s.time_since_epoch().count()),
static_cast(__ns.count())
  };
This definition uses a braced-init-list that has two elements and is unsuitable 
for scalar types.

> If the current code assumes a struct and the Windows API calls need an
> integer then either the existing code needs to be made more flexible,
> or you need to define it as a struct and then convert to an integer
> inside your new gthread wrapper functions.

The Windows APIs involved use LARGE_INTEGER - a union of a 64-bit integer and 
an array of two 32-bit integers - because some languages might have no native 
64-bit integer types.
Actually in C99 and C++11 we just assume there is long long and int64_t despite 
the fact that ISO C marks int64_t as optional, so it can be regarded as a union 
whose only element is an int64_t.

> std::condition_variable::__clock_t must be a typedef for the clock
> used by the underlying implementation, so it sounds like you should
> use std::chrono::steady_clock for your thread model.

> All conversions are done using the std::chrono facilities, before any
> conversion to __gthread_time_t. That means the conversions are
> portable.

Thought so. I have to take a deep look.
 
Thanks for your help!



--   
Best regards,
lh_mouse
2016-04-18



Re: Re: Re: Adding a new thread model to GCC

2016-04-18 Thread lh_mouse
>>> If the current code assumes a struct and the Windows API calls need an
>>> integer then either the existing code needs to be made more flexible,
>>> or you need to define it as a struct and then convert to an integer
>>> inside your new gthread wrapper functions.
>>
>> The Windows APIs involved use LARGE_INTEGER - a union of a 64-bit integer 
>> and an array of two 32-bit integers - because some languages might have no 
>> native 64-bit integer types.
>> Actually in C99 and C++11 we just assume there is long long and int64_t 
>> despite the fact that ISO C marks int64_t as optional, so it can be regarded 
>> as a union whose only element is an int64_t.
>> 
> What are the units of the argument? Milliseconds?

>From Windows SDK:
  File Times
  A file time is a 64-bit value that represents the number of 100-nanosecond 
intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated 
Universal Time (UTC).

This decision makes it much easier to count leap years, no?

> You have two choices, either modify all the places in libstdc++ that
> use __gthread_time_t, changing the code to use some new function
> template that populates a __gthread_time_t from a
> std::chrono::time_point or std::chrono::duration, or define
> a similar struct in your gthreads header and convert it to int64_t
> inside your functions.  For functions taking a relative time the
> conversion from a { seconds, nanoseconds } struct to milliseconds is
> trivial, for functions taking an absolute time you need to know the
> epoch of the clock that was used when populating the struct.

Will do that next week. Still need to make gcc work with my library.

--   
Best regards,
lh_mouse
2016-04-18




Re: Re: Re: Adding a new thread model to GCC

2016-04-19 Thread lh_mouse
Thanks to ktietz, Elieux, mingwandroid (via IRC) and jwakely (via mail), 
the integration of mcfgthread and gcc has been accomplished.

This 9000- patch applies to the gcc-5-branch after all other patches from
https://github.com/Alexpux/MINGW-packages/tree/master/mingw-w64-gcc-git are 
applied.
After applying the patches please run 'configure' with --enable-threads=mcf.
The newly compiled i686 gcc has passed 3-stages bootstrap and seems working.
I am going to start the x64 build very soon.

Source code and pre-built binaries of the 'mcfgthread' library can be found 
here:
https://github.com/lhmouse/mcfgthread/tree/master/release
Problem reports and suggestions are welcome. :>

Thanks for your help and interest!


--   
Best regards,
lh_mouse
2016-04-19


9000-Added-mcf-thread-model-support-from-mcfgthread.patch
Description: Binary data


mcfgthread-release-i686-x86_64.7z
Description: Binary data


Re: Re: Re: Adding a new thread model to GCC

2016-04-20 Thread lh_mouse
One more question about block-scoped static objects:

>From compiled assembly I have learned that GCC uses a 64-bit integer guard to 
>ensure once-initialization of static objects with block scopes.
Code in gcc/libstdc++-v3/libsupc++/guard.cc uses a global mutex to protect 
multiple threads from racing, which, as described in that file, could 
potentially cause a deadlock that can be avoided if a condition variable is 
used.

This, however, is unnecessary with mcfgthread. The mcfgthread library uses the 
once_flag itself as both the mutex and condition variable, eliminating the need 
of a global mutex and condition variable.
Code using mcfgthread might look like this:
[code]

class foo { ... };

static ::_MCFCRT_OnceFlag flag;
static alignas(foo) char obj[sizeof(foo)];

foo *get_obj(){
const auto construct_obj = []{ ::new(static_cast(obj)) foo(); };
const auto destruct_obj  = []{ reinterpret_cast(obj)->~foo(); };

// Lock the once flag as if it were a mutex.
const auto result = ::_MCFCRT_WaitForOnceFlagForever(&flag); 
// This never times out, so result can be either _MCFCRT_kOnceResultInitial 
or _MCFCRT_kOnceResultFinished.
if(result == ::_MCFCRT_kOnceResultInitial){
try {
// Construct the object in-place.
construct_obj();
if(std::atexit(&destruct_obj) != 0){
// Assume we have run out of memory.
destruct_obj();
throw std::bad_alloc();
}
} catch(...){
// Unlock the once flag, allowing other threads to retry the 
initialization.
// This works like pthread_cond_signal().
::_MCFCRT_SignalOnceFlagAsAborted(&flag);
throw;
}
// We are done here. Unlock the once flag and other threads will not be 
blocked any more.
// This works like pthread_cond_broadcast().
_MCFCRT_SignalOnceFlagAsFinished(&flag);
}
return reinterpret_cast(obj);
}
[/code]

Now here is my question:
That '__cxxabiv1::__guard' thing seems built-in of GCC. Does it have anything 
to do with code generation? And where is it involved?

--   
Best regards,
lh_mouse
2016-04-20



Re: Why does gcc generate const local array on stack?

2016-04-20 Thread lh_mouse
I tend to say clang is wrong here.

Quoting the standard:

ISO/IEC WG14 Draft N1570 (Programming languages — C):
[quote]
6.2.2 Linkages of identifiers
6 The following identifiers have no linkage: an identifier declared to be 
anything other than
an object or a function; an identifier declared to be a function parameter; a 
block scope
identifier for an object declared without the storage-class specifier extern.

6.2.4 Storage durations of objects
6 An object whose identifier is declared with no linkage and without the 
storage-class
specifier static has automatic storage duration, as do some compound literals. 
...
7 For such an object that does have a variable length array type, its lifetime 
extends from
the declaration of the object until execution of the program leaves the scope 
of the
declaration.35) If the scope is entered recursively, a new instance of the 
object is created
each time. The initial value of the object is indeterminate.
[/quote]

Your identifier 'a' has no linkage. Your object designated by 'a' does not have 
a storage-class specifier.
So it has automatic storage duration and 6.2.4/7 applies: 'If the scope is 
entered recursively, a new instance of the object is created each time.'

Interesting enough, ISO C doesn't say whether distinct objects should have 
distinct addresses.
It is worth noting that this is explicitly forbidden in ISO C++ because 
distinct complete objects shall have distinct addresses:

ISO/IEC WG21 N4582 (Working Draft, Standard for Programming Language C++) :
[quote]
1.9 Program execution [intro.execution]
7 An instance of each object with automatic storage duration (3.7.3) is 
associated with each entry into its
block. Such an object exists and retains its last-stored value during the 
execution of the block and while the
block is suspended (by a call of a function or receipt of a signal).

1.8 The C++ object model [intro.object]
6 Unless an object is a bit-field or a base class subobject of zero size, the 
address of that object is the address of
the first byte it occupies. Two objects that are not bit-fields may have the 
same address if one is a subobject
of the other, or if at least one is a base class subobject of zero size and 
they are of different types; otherwise,
they shall have distinct addresses.4
[/quote]


--   
Best regards,
lh_mouse
2016-04-20

-
发件人:Bingfeng Mei 
发送日期:2016-04-20 23:38
收件人:gcc
抄送:
主题:Why does gcc generate const local array on stack?

Hi,
I came across the following issue.

int foo (int N)
{
  const int a[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

  return a[N];
}

Compile with x86 O2

foo:
.LFB0:
.cfi_startproc
movslq %edi, %rdi
movl $0, -56(%rsp)
movl $1, -52(%rsp)
movl $2, -48(%rsp)
movl $3, -44(%rsp)
movl $4, -40(%rsp)
movl $5, -36(%rsp)
movl $6, -32(%rsp)
movl $7, -28(%rsp)
movl $8, -24(%rsp)
movl $9, -20(%rsp)
movl -56(%rsp,%rdi,4), %eax
ret

The array is placed on stack and GCC has to generate a sequence of
instructions to
initialize the array every time the function is called.

On the contrary, LLVM moves the array to global data and doesn't need
initialization
within the function.

If I add static to the array, GCC behaves the same as LLVM, just as expected.

Is there some subtle C standard issue or some switch I didn't turned
on? I understand
if this function is recursive and pointer of the array is involved,
GCC would have to maintain
the array on stack and hence the initialization. But here the code is
very simple. I don't understand the logic of generated code, or maybe
missing optimization opportunity?

Thanks,
Bingfeng Mei




Re: Re: Why does gcc generate const local array on stack?

2016-04-20 Thread lh_mouse
See this example: http://coliru.stacked-crooked.com/a/048b4aa5046da11b

In this example the function is called recursively.
During each call a pointer to that local areay is appended to a static array of 
pointers.
Should a new instance of that local array of const int be created every time, 
abort() will never be called.
Since calling a library function is observable behavior, clang's optimization 
has effectively changed that program's behavior. Hence I think it is wrong.

[code]
#include 

static const int *ptrs[2];
static unsigned recur;

void foo(){
  const int a[] = {0,1,2,3,4,5,6,7,8,9};
  ptrs[recur] = a;
  if(recur == 0){
++recur;
foo();
  }
  if(ptrs[0] == ptrs[1]){
abort();
  }
}

int main(){
  foo();
}
[/code]

--   
Best regards,
lh_mouse
2016-04-21

-
发件人:Jonathan Wakely 
发送日期:2016-04-21 01:51
收件人:lh_mouse
抄送:Bingfeng Mei,gcc
主题:Re: Why does gcc generate const local array on stack?

On 20 April 2016 at 18:31, lh_mouse wrote:
> I tend to say clang is wrong here.

If you can't detect the difference then it is a valid transformation.

> Your identifier 'a' has no linkage. Your object designated by 'a' does not 
> have a storage-class specifier.
> So it has automatic storage duration and 6.2.4/7 applies: 'If the scope is 
> entered recursively, a new instance of the object is created each time.'

How do you tell the difference between a const array that is recreated
each time and one that isn't?

> Interesting enough, ISO C doesn't say whether distinct objects should have 
> distinct addresses.
> It is worth noting that this is explicitly forbidden in ISO C++ because 
> distinct complete objects shall have distinct addresses:

If the object's address doesn't escape from the function then I can't
think of a way to tell the difference.




GCC 6.1 Hard-coded C++ header paths and relocation problem on Windows

2016-05-02 Thread lh_mouse
This is a cross-post from gcc-help as there haven't been any replies on 
gcc-help since two days ago. Hope someone could help.
```

I have built GCC from gcc-6-branch in MSYS2 with mingw-w64 CRT on Windows today.
Now I have a relocation problem:

Assuming mingw-w64 headers are located in the follow directory,which is, the 
native_system_header_dir:
> C:/MinGW/MSYS2/mingw32/lib/gcc/i686-w64-mingw32/6.1.1/include
I have built GCC and it has that hard-coded path.
When I compile something using g++ -v, the headers are searched in the 
following paths:
```
ignoring nonexistent directory "/mingw32/include"
ignoring duplicate directory "C:/MinGW/MSYS2/mingw32/i686-w64-mingw32/include"
#include "..." search starts here:
#include <...> search starts here:
 C:/MinGW/MSYS2/mingw32/include/c++/6.1.1
 C:/MinGW/MSYS2/mingw32/include/c++/6.1.1/i686-w64-mingw32
 C:/MinGW/MSYS2/mingw32/include/c++/6.1.1/backward
 C:/MinGW/MSYS2/mingw32/lib/gcc/i686-w64-mingw32/6.1.1/include
 C:/MinGW/MSYS2/mingw32/lib/gcc/i686-w64-mingw32/6.1.1/../../../../include
 C:/MinGW/MSYS2/mingw32/lib/gcc/i686-w64-mingw32/6.1.1/include-fixed
 
C:/MinGW/MSYS2/mingw32/lib/gcc/i686-w64-mingw32/6.1.1/../../../../i686-w64-mingw32/include
End of search list.
```
The C++ headers are searched before any mingw-w64 headers, which is just fine.

However, if I move gcc to another directory, let's say, 
C:/this_is_a_new_directory/mingw32/,
then re-compile the same program with g++ -v, the headers are searched in the 
following paths:
```
ignoring duplicate directory 
"C:/this_is_a_new_directory/mingw32/lib/gcc/../../lib/gcc/i686-w64-mingw32/6.1.1/include"
ignoring nonexistent directory "C:/MinGW/MSYS2/mingw32/include"
ignoring nonexistent directory "/mingw32/include"
ignoring duplicate directory 
"C:/this_is_a_new_directory/mingw32/lib/gcc/../../lib/gcc/i686-w64-mingw32/6.1.1/include-fixed"
ignoring duplicate directory 
"C:/this_is_a_new_directory/mingw32/lib/gcc/../../lib/gcc/i686-w64-mingw32/6.1.1/../../../../i686-w64-mingw32/include"
ignoring nonexistent directory "C:/MinGW/MSYS2/mingw32/i686-w64-mingw32/include"
#include "..." search starts here:
#include <...> search starts here:
 
C:/this_is_a_new_directory/mingw32/bin/../lib/gcc/i686-w64-mingw32/6.1.1/include
 
C:/this_is_a_new_directory/mingw32/bin/../lib/gcc/i686-w64-mingw32/6.1.1/../../../../include
 
C:/this_is_a_new_directory/mingw32/bin/../lib/gcc/i686-w64-mingw32/6.1.1/include-fixed
 
C:/this_is_a_new_directory/mingw32/bin/../lib/gcc/i686-w64-mingw32/6.1.1/../../../../i686-w64-mingw32/include
 C:/this_is_a_new_directory/mingw32/lib/gcc/../../include/c++/6.1.1
 
C:/this_is_a_new_directory/mingw32/lib/gcc/../../include/c++/6.1.1/i686-w64-mingw32
 C:/this_is_a_new_directory/mingw32/lib/gcc/../../include/c++/6.1.1/backward
End of search list.
```
This time the C++ headers are searched after mingw-w64 headers, which causes 
the following error:
```
In file included from 
C:/MinGW/mingw32/include/c++/6.1.1/ext/string_conversions.h:41:0,
 from 
C:/MinGW/mingw32/include/c++/6.1.1/bits/basic_string.h:5402,
 from C:/MinGW/mingw32/include/c++/6.1.1/string:52,
 from 
C:/MinGW/mingw32/include/c++/6.1.1/bits/locale_classes.h:40,
 from C:/MinGW/mingw32/include/c++/6.1.1/bits/ios_base.h:41,
 from C:/MinGW/mingw32/include/c++/6.1.1/ios:42,
 from C:/MinGW/mingw32/include/c++/6.1.1/ostream:38,
 from C:/MinGW/mingw32/include/c++/6.1.1/iostream:39,
 from test.cpp:1:
C:/MinGW/mingw32/include/c++/6.1.1/cstdlib:75:25: fatal error: stdlib.h: No 
such file or directory
 #include_next 
 ^
compilation terminated.
```

Do you know how to solve this problem (modifications to gcc source code are 
expected)?
Thanks in advance.



--
Best regards,
lh_mouse
2016-05-02



Re: GCC 6.1 Hard-coded C++ header paths and relocation problem on Windows

2016-05-02 Thread lh_mouse
I made some investigation yesterday and here is the result:
```

Diff'ing gcc/libstdc++-v3/include/c_global/cstdlib from gcc-5-branch and 
gcc-6-branch gives the following result:
(git diff gcc-5-branch gcc-6-branch -- libstdc++-v3/include/c_global/cstdlib)
```
@@ -69,7 +69,11 @@ namespace std
 
 #else
 
-#include 
+// Need to ensure this finds the C library's  not a libstdc++
+// wrapper that might already be installed later in the include search path.
+#define _GLIBCXX_INCLUDE_NEXT_C_HEADERS
+#include_next 
+#undef _GLIBCXX_INCLUDE_NEXT_C_HEADERS
 
 // Get rid of those macros defined in  in lieu of real functions.
 #undef abort
```
Replacing #include_next with #include fixes the problem.

However, I am not exactly clear about whether it is these headers (cstdlib and 
cmath currently, there might be more) that are the problem.
In my point of view, it is the inversion of C and C++ header paths that is the 
problem.



--   
Best regards,
lh_mouse
2016-05-02



Re: Re: GCC 6.1 Hard-coded C++ header paths and relocation problem on Windows

2016-05-03 Thread lh_mouse
Should I file a bug report then?
We need some Linux testers, though not many people on Linux relocate compilers.

--   
Best regards,
lh_mouse
2016-05-03

-
发件人:Jonathan Wakely 
发送日期:2016-05-03 17:00
收件人:lh_mouse
抄送:gcc
主题:Re: GCC 6.1 Hard-coded C++ header paths and relocation problem on Windows

On 2 May 2016 at 11:41, lh_mouse wrote:
> However, I am not exactly clear about whether it is these headers (cstdlib 
> and cmath currently, there might be more) that are the problem.

No, it's only those two.

> In my point of view, it is the inversion of C and C++ header paths that is 
> the problem.

Agree. I don't know why that happens though.