[Bug c++/50087] [C++0x] Weird optimization anomaly with constexpr

2011-09-13 Thread eric-gcc at omnifarious dot org
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

2010-12-06 Thread eric-gcc at omnifarious dot org
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

2010-12-06 Thread eric-gcc at omnifarious dot org
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

2011-08-15 Thread eric-gcc at omnifarious dot org
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

2011-08-15 Thread eric-gcc at omnifarious dot org
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

2006-03-02 Thread eric-gcc at omnifarious dot org


--- 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

2020-11-23 Thread eric-gcc at omnifarious dot org via Gcc-bugs
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

2020-11-23 Thread eric-gcc at omnifarious dot org via Gcc-bugs
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   )

:   /**