[Bug c++/50087] [C++0x] Weird optimization anomaly with constexpr
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50087 --- Comment #7 from eric-gcc at omnifarious dot org 2011-09-13 22:15:16 UTC --- (In reply to comment #6) > (In reply to comment #5) > > I still think it's a missed optimization opportunity. > > Yes, it definitely is. I'm just not sure whether it should be fixed by doing > constexpr expansion in non-constant expression contexts in some cases, or > improving normal optimization to handle this case. That's an interesting question. I think improving normal optimization to handle this case might prove to be rather tricky. It would basically require detecting that a function could be constexpr even if it wasn't declared that way. Otherwise, a deep recursion case like this is really a pain to deal with at optimization time. I can think of cases where I have created templates for finding GCDs (using Euclid's algorithm), integer logarithms and integer exponents at compile time that are not toy problems. GCDs in particular are at least is tricky as the silly bad recursive Fibonacci number generator. Of course, I'm only guessing. Compilers and optimizers are not my thing. It just seems like using the constexpr logic in some cases would be a lot easier.
[Bug c++/46827] New: Heavy use of namespaces leads to cluttered and difficult to read header files
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46827 Summary: Heavy use of namespaces leads to cluttered and difficult to read header files Product: gcc Version: unknown Status: UNCONFIRMED Severity: enhancement Priority: P3 Component: c++ AssignedTo: unassig...@gcc.gnu.org ReportedBy: eric-...@omnifarious.org Header files with declarations like this: void FooBar(System::Network::Win32::Sockets::Handle handle, System::Network::Win32::Sockets::Error& error /*, more fully-qualified param declarations... */); are common in certain frameworks. And using declarations, which could mitigate this problem, are generally not considered kosher to use in header files because they can effect the name lookup rules for header files that are included later. typedefs inside a class that are declared private clutter up the class' namespace and the namespace of classes derived from it. Here is a proposed solution: using { // A 'using' block is a sort of way to fence names in. The only names // that escape the confines of a using block are names that are not // aliases for other things, not even for things that don't have names // of their own. These are things like the declarations for new // classes, enums, structs, global functions or global variables. // New, non-alias names will be treated as if they were declared in // the scope in which the 'using' block appeared. using namespace ::std; using ::mynamespace::mytype_t; namespace mn = ::mynamespace; using ::mynamespace::myfunc; class AClass { public: typedef mytype_t atype_t; AClass(const string &st, mytype_t me) : st_(st), me_(me) { myfunc(&me_); } private: const string st_; mn::mytype_t me_; }; typedef struct { int a; } simple; // The effects of all typedefs, using declarations, and namespace // aliases that were introduced at the level of this block go away // here. typedefs and using declarations inside of nested classes // or namespace declarations do not go away. } // end using. // Legal because AClass is treated as having been declared in this // scope. AClass a("Fred", ::mynamespace::mytype_t(5)); // Not legal, alias mn no longer exists. AClass b("Fred", mn::mytype_t); // Not legal, the using directive bringing in mytype_t is no longer in effect AClass b("Fred", mytype_t); // Not legal, the using directing bringing in myfunc is no longer in effect. AClass c("Fred", myfunc(::mynamespace::mytype_t(5)); // Legal, only names declared at level of the using block disappear. names // declared in nested sub-blocks (like namespace or class declarations) do not. AClass d("Fred", AClass::atype_t(5)); // Not legal, the name simple, being an alias for an anonymous structure, // disappeared at the end of the using block. simple e; Java, Python and other languages have ways of bringing in names from other namespaces with a very limited scope. In Java, the import directive brings in a name that only exists for the duration of the .java file. In Python, the import statement can bring names into a module from outside, and it's relatively easy to prevent those names from being easily exported outside the module. C++ needs a similar mechanism. The existence of the preprocessor the #include directive and the C++ concept of a translation unit make the implicit scoping of imported names problematic. So some mechanism for explicitly scoping such temporary aliases is needed. Hence my above proposal of the 'using' block.
[Bug c++/46827] Heavy use of namespaces leads to cluttered and difficult to read header files
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46827 --- Comment #2 from eric-gcc at omnifarious dot org 2010-12-06 20:19:51 UTC --- (In reply to comment #1) > I think you should proposal this to the C++ standards committee instead of > posting a full request here. I don't know how to do that in a way it will be listened to.
[Bug c++/50087] New: Weird optimization anomoly with constexpr
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50087 Bug #: 50087 Summary: Weird optimization anomoly with constexpr Classification: Unclassified Product: gcc Version: 4.6.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ AssignedTo: unassig...@gcc.gnu.org ReportedBy: eric-...@omnifarious.org Created attachment 25014 --> http://gcc.gnu.org/bugzilla/attachment.cgi?id=25014 runs_too_long runs in a very short period of time I have two nearly identical programs. In one (small.joe.cpp), a function called 'runs_too_long' does not run too long. It is compiled down to returning a constant value. In another, very slightly different program (small-nojoe.cpp), the function 'runs_too_long' does indeed run too long. It, in fact will not complete in any reasonable length of time.
[Bug c++/50087] Weird optimization anomoly with constexpr
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50087 --- Comment #1 from eric-gcc at omnifarious dot org 2011-08-15 12:49:16 UTC --- Created attachment 25015 --> http://gcc.gnu.org/bugzilla/attachment.cgi?id=25015 The function 'runs_too_long' takes basically forever
[Bug tree-optimization/14703] Inadequate optimization of inline templated functions
--- Comment #6 from eric-gcc at omnifarious dot org 2006-03-02 20:25 --- I'm pleased that I came up with such a difficult test case for the optimizer. I never thought it'd be that hard. :-) I don't know anything about the internals, but... The compiler has to generate everything down to the fibconst<0> and fibconst<1> specializations anyway. So why can't it memoize and filter the optimization up? Say it generates fibconst<1> and fibconst<2> in order to generate fibconst<3>, then it discovers that fibconst<3> can be optimized to return plain old '3'. It can save that, and then when it comes down again needing fibconst<2> and fibconst<3> in order to generate fibconst<4>, it can see the already optimized version of fibconst<3> and generate an optimized version of fibconst<4> that just returns plain old '5'. Maybe I have things totally wrong and there's no way to do anything like that with the code. Or maybe it would turn out that that way of doing things is so special case that it's not worth bothering with. But, I just wonder if memoizing some sort of optimized version of a function would help with a lot of things. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=14703
[Bug c++/97952] New: Poor optimization of closure-like construct in C++ as compared to C
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97952 Bug ID: 97952 Summary: Poor optimization of closure-like construct in C++ as compared to C Product: gcc Version: 10.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: eric-gcc at omnifarious dot org Target Milestone: --- This code generates about 400+ lines of assembly: https://gcc.godbolt.org/z/s9s9Mx and this essentially equivalent C code generates only 100+ lines: https://gcc.godbolt.org/z/5abWEe This seems like poor optimization in C++. The C code makes use of nested functions, a GCC specific feature. And the C++ code uses a class to simulate a closure, thereby accomplishing essentially the same goal.
[Bug c++/97952] Poor optimization of closure-like construct in C++ as compared to C
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97952 --- Comment #1 from eric-gcc at omnifarious dot org --- Because you might not like Godbolt links, here is the C code: //---cut here--- /*** core string search routine ***/ typedef char *String; typedef unsigned longIndex, Count, Size, Length, Limit, Extent, Mask, Bits; typedef struct { const String string; const Length length; const Index *const table; } SearchString_data; typedef SearchString_data *SearchString, SearchString_object[1]; enum { IAC = (char) 255, WILL= (char) 251, WONT= (char) 252, DO = (char) 253, DONT= (char) 254, }; static Length command_length( String s, String sn ); static Length command_length_unknown( String s, String sn ); String skip_past( String input, String sn, SearchString ss ){ const Index *walkback = ss->table; const Index kn = ss->length; const String w= ss->string; typedef String Skip_f( String, Index ); auto Skip_f skip_zero, skip_one_half, skip_one, command_skip_zero, command_skip,skip; return skip_zero( input, 0 ); String skip_zero( String s, Index k ){ return k == kn ? s : skip_one_half( s, k ); } String skip_one_half( String s, Index k ){ return s == sn ? 0 : skip_one( s, k ); } String skip_one( String s, Index k ){ return 0[s] == IAC ? command_skip_zero( s+1, k ) : skip( s, k ); } String command_skip_zero( String s, Index k ){ return s == sn ? 0 : 0[s] != IAC ? command_skip( s, k ) : /** IAC IAC **/skip( s, k ); } String command_skip( String s, Index k ){ Count m = command_length( s, sn ); Count n = sn - s; return m > n ? 0 : skip_one_half( s+m, k ); } String skip( String s, Index k ){ return 0[s] == w[k]? skip_zero( s+1, k+1 ) : k == 0 ? skip_one_half( s+1, 0 ) : /** !=, k > 0 **/ skip( s, walkback[k] ); } } Length command_length( String s, String sn ){ return *s == IAC ? 1 : *s == WILL ? 2 : *s == WONT ? 2 : *s == DO? 2 : *s == DONT ? 2 : /*** otherwise ***/command_length_unknown( s, sn ) ; } Length command_length_unknown( String s, String sn ){ return 1; // TBD - is there something better here? } //---cut here--- and here is the C++ code: //---cut here--- /*** core string search routine ***/ typedef char *String; typedef unsigned longIndex, Count, Size, Length, Limit, Extent, Mask, Bits; typedef struct { const String string; const Length length; const Index *const table; } SearchString_data; typedef SearchString_data *SearchString, SearchString_object[1]; enum : char { IAC = (char) 255, WILL= (char) 251, WONT= (char) 252, DO = (char) 253, DONT= (char) 254, }; static Length command_length( String s, String sn ); static Length command_length_unknown( String s, String sn ); String skip_past3( String input, String sn, SearchString ss ) { class search_closure { public: search_closure( String input, String sn, SearchString ss ) : input(input), sn(sn), ss(ss), walkback(ss->table), kn(ss->length), w(ss->string) {} String operator ()() const { return skip_zero( input, 0); } private: const String input; const String sn; const SearchString ss; const Index *walkback; const Index kn; const String w; String skip_zero( String s, Index k ) const { return k == kn ? s : skip_one_half( s, k ); } String skip_one_half( String s, Index k ) const { return s == sn ? 0 : skip_one( s, k ); } String skip_one( String s, Index k ) const { return 0[s] == IAC ? command_skip_zero( s+1, k ) : skip( s, k ); } String command_skip_zero( String s, Index k ) const { return s == sn ? 0 : 0[s] != IAC ? command_skip( s, k ) : /** IAC IAC **/skip( s, k ); } String command_skip( String s, Index k ) const { Count m = command_length( s, sn ); Count n = sn - s; return m > n ? 0 : skip_one_half( s+m, k ); } String skip( String s, Index k ) const { return 0[s] == w[k]? skip_zero( s+1, k+1 ) : k == 0 ? skip_one_half( s+1, 0 ) : /**