[Bug libstdc++/109022] New: Low performance of std::map constructor for already sorted data of std::pair

2023-03-04 Thread marekr22 at wp dot pl via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109022

Bug ID: 109022
   Summary: Low performance of std::map constructor for already
sorted data of std::pair
   Product: gcc
   Version: 12.2.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: libstdc++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: marekr22 at wp dot pl
  Target Milestone: ---

Performance of constructor accepting iterators to sorted data of
std::pair is much lower then inserting same data for
std::pair (matches value_type of std::map).

Here is benchmark showing the issue:
```
#include 
#include 
#include 
#include 
#include 

constexpr size_t DataSizeStart = 8 << 0;
constexpr size_t DataSizeStop = 8 << 3;

using TestData = std::vector>;
using TestDataConst = std::vector>;

std::string makeStringFor(size_t x)
{
  std::ostringstream out;
  out << std::setfill('0') << std::setw(6) << x;
  return out.str();
}

TestData sortedData(size_t n)
{
  TestData r;
  r.reserve(n);
  size_t i = 0;
  std::generate_n(std::back_inserter(r), n, []() {
return std::pair{makeStringFor(++i), i};
  });
  return r;
}

TestData shuffledData(size_t n)
{
  auto data = sortedData(n);
  std::random_device rd;
  std::mt19937 g(rd());

  std::shuffle(data.begin(), data.end(), g);
  return data;
}

TestDataConst sortedConstData(size_t n)
{
  auto r = sortedData(n);
  return {r.begin(), r.end()};
}

TestDataConst shuffledConstData(size_t n)
{
  auto r = shuffledData(n);
  return {r.begin(), r.end()};
}

template
static void CreateMapInsert(benchmark::State& state) {
  auto n = state.range(0);
  auto data = Data(n);
  for (auto _ : state) {
benchmark::DoNotOptimize(data);
std::map m;

for (auto& p : data) {
  m.insert(m.end(), p);
}
benchmark::DoNotOptimize(m);
  }
}
BENCHMARK(CreateMapInsert)->RangeMultiplier(2)->Range(DataSizeStart,
DataSizeStop);
//
BENCHMARK(CreateMapInsert)->RangeMultiplier(2)->Range(DataSizeStart,
DataSizeStop);
BENCHMARK(CreateMapInsert)->RangeMultiplier(2)->Range(DataSizeStart,
DataSizeStop);
//
BENCHMARK(CreateMapInsert)->RangeMultiplier(2)->Range(DataSizeStart,
DataSizeStop);

template
static void CreateMapDirectly(benchmark::State& state) {
  auto n = state.range(0);
  auto data = Data(n);
  for (auto _ : state) {
benchmark::DoNotOptimize(data);
std::map m{data.begin(), data.end()};
benchmark::DoNotOptimize(m);
  }
}
BENCHMARK(CreateMapDirectly)->RangeMultiplier(2)->Range(DataSizeStart,
DataSizeStop);
//
BENCHMARK(CreateMapDirectly)->RangeMultiplier(2)->Range(DataSizeStart,
DataSizeStop);
BENCHMARK(CreateMapDirectly)->RangeMultiplier(2)->Range(DataSizeStart,
DataSizeStop);
//
BENCHMARK(CreateMapDirectly)->RangeMultiplier(2)->Range(DataSizeStart,
DataSizeStop);
```

Live demo gcc 12.2: https://quick-bench.com/q/H8lqugNgMG-sWQ6cKBsdB7EBRpU
Note that CreateMapInsert performs best since it feeds to
constructos to iterators to std::pair while
CreateMapInsert performs badly (looks like time complexity is
worse) adn only diffrence is that it provides iterators to std::.

Same issue is observed for clang 14.0 and libstdc++:
https://quick-bench.com/q/6VA3vRdKmqPEYrvTnFFla4gxwXk
but it is not a problem on clang 14.0 and libc++:
https://quick-bench.com/q/-S-lX3N8Y-8vL9CCl-5bW5jolWA

here is result for sing size input data (easier to read):
https://quick-bench.com/q/kbDOPA8PNZFfrzUH_-70cJgApeE

Issue was observed when filing answer on
https://stackoverflow.com/a/75535056/1387438

[Bug c++/102493] New: non-type template specialization for member pointer to field and function reports leads to unexpected conflict

2021-09-26 Thread marekr22 at wp dot pl via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102493

Bug ID: 102493
   Summary: non-type template specialization for member pointer to
field and function reports leads to unexpected
conflict
   Product: gcc
   Version: 11.1.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: marekr22 at wp dot pl
  Target Milestone: ---

Here is minimum complete verifiable example (C++17):
```cpp
#include 
#include 
#include 

template 
struct field_type;

template
struct field_type
{
using type = R;
};

template
struct field_type
{
using type = R;
}; 

template
using field_type_t = typename field_type::type;


class Foo {
public:
int x = 0;
double y = 0;
std::string s;
const int cx = 0;

Foo() = default;

void bar() {
std::cout << "bar\n";
}

int par(int z) {
std::cout << "bar\n";
return z;
}
};

template
constexpr bool test = std::is_same_v, T>;

static_assert(test<::x,int>, "");
static_assert(test<::cx,   const int>,   "");
static_assert(test<::s,std::string>, "");
static_assert(test<::y,double>,  "");
#ifndef HIDE_PROBLEM_ON_GCC_11
static_assert(test<::bar,  void>,"");
static_assert(test<::par,  int>, "");
#endif
```

This compile on all compilers https://godbolt.org/z/31svobz3z
except for gcc 11.1 and 11.2 (gcc 10.3 works).

Reported error is:
```
: In substitution of 'template using field_type_t = typename
field_type::type [with auto FP = ::bar]':
:44:28:   required from 'constexpr const bool test<::bar, void>'
:51:15:   required from here
:21:7: error: ambiguous template instantiation for 'struct
field_type<::bar>'
   21 | using field_type_t = typename field_type::type;
  |   ^~~~
:9:8: note: candidates are: 'template
struct field_type [with R = void(); T = Foo; R T::* FP = ::bar]'
9 | struct field_type
  |^~
:15:8: note: 'template struct field_type [with R = void; T = Foo;
Args = {}; R (T::* FP)(Args ...) = ::bar]'
   15 | struct field_type
  |^~
:21:7: error: invalid use of incomplete type 'struct
field_type<::bar>'
   21 | using field_type_t = typename field_type::type;
  |   ^~~~
:6:8: note: declaration of 'struct field_type<::bar>'
6 | struct field_type;
  |^~
```

[Bug c++/98798] New: Custom operator new[] and delete[] is buggy for aligned class

2021-01-22 Thread marekr22 at wp dot pl via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98798

Bug ID: 98798
   Summary: Custom operator new[] and delete[] is buggy for
aligned class
   Product: gcc
   Version: 11.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: marekr22 at wp dot pl
  Target Milestone: ---

Basically when class has alignment requirement and custom operators `new[]` and
`delete[]` (C++17), then address sanitizer reports buffer overflow:

## MCVE:
```cpp
#include 
#include 

class EndlineOnDone {
std::ostream& out;
public:
EndlineOnDone(std::ostream& out) : out{out} {}
~EndlineOnDone()
{
out << std::endl;
}
std::ostream& stream() { return out; }
};

#define VAR(x) " " #x "=[" << x << "]" 
#define LOG EndlineOnDone(std::cout).stream() << __PRETTY_FUNCTION__

std::ostream& operator<<(std::ostream& out, std::align_val_t a)
{
return out << static_cast(a);
}

class alignas(32) Foo
{
public :
double x, y, z;

void * operator new (size_t s, std::align_val_t a)
{
auto p = aligned_alloc(static_cast(a), s);
LOG << VAR(p) << VAR(s) << VAR(a);
return p;
}

void operator delete (void * p, size_t s, std::align_val_t a)
{
LOG << VAR(p) << VAR(s) << VAR(a);
if (p) free(p);
}

#if 1
void * operator new[ ] (size_t s, std::align_val_t a)
{
auto p = aligned_alloc(static_cast(a), s);
LOG << VAR(p) << VAR(s) << VAR(a);
return p;
}

void operator delete[ ] (void *p, size_t s, std::align_val_t a)
{
LOG << VAR(p) << VAR(s) << VAR(a);
if (p) free(p);
}
#endif
};

int main()
{
{
LOG << " std::make_unique";
auto p = std::make_unique();
}

{
LOG << " std::make_unique";
auto p = std::make_unique(3);
}
}
```
https://godbolt.org/z/7xd8YM

## gcc logs (no address sanitizer):
```txt
int main() std::make_unique
static void* Foo::operator new(size_t, std::align_val_t) p=[0x21d6ec0] s=[32]
a=[32]
static void Foo::operator delete(void*, size_t, std::align_val_t) p=[0x21d6ec0]
s=[32] a=[32]
int main() std::make_unique
static void* Foo::operator new [](size_t, std::align_val_t) p=[0x21d6f40]
s=[96] a=[32]
static void Foo::operator delete [](void*, size_t, std::align_val_t)
p=[0x21d6f40] s=[3616] a=[32]
```
Note that `s` value for `Foo[]` doesn't match for `new[]` and `delete[]`
operations.

Address sanitizer reports buffer overflow.

clang is fine (didn't check msvc).

## Workaround
Adding explicit destructor `~Foo() {}` fixes this issue:
https://godbolt.org/z/WoM91Y (use of `~Foo() = default;` doesn't fix it).


https://stackoverflow.com/q/65826663/1387438