[Bug c++/97952] Poor optimization of closure-like construct in C++ as compared to C

2021-04-25 Thread pinskia at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97952

Andrew Pinski  changed:

   What|Removed |Added

   Severity|normal  |enhancement

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

:   /** !=, k > 0 **/  skip( s,