llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
29.13k stars 12.01k forks source link

Memory allocation elision for std::vector cases #108407

Open apolukhin opened 2 months ago

apolukhin commented 2 months ago

Code close to the following was noted in many user applications:

bool test1(const std::vector<std::string_view>& in) {
    return in == std::vector<std::string_view>{"*"};
}

Here people wish to make sure that the vector contains only a single "*" element. In other words they assume that the above code snippet would be optimized to something like:

bool test2(const std::vector<std::string_view>& in) {
    return in.size() == 1 && in[0] == "*";
}

Unfortunately that does not happen: https://godbolt.org/z/8WThj5Mrq

Note that all the functions are inlined however the new+delete are not elided.

Minimized example: https://godbolt.org/z/T8a8a8nxq

efriedma-quic commented 2 months ago

Briefly glanced at this.

The loop optimizer isn't handling the size() call well; the whole thing optimizes much better with the following (obviously not correct in general, but should be equivalent here):

template <typename _Tp>
constexpr inline bool operator==(const vector<_Tp>& __x,
                                 const vector<_Tp>& __y) {
    return  __x._M_start + 1 == __x._M_finish &&
            equal(__x.data(), __x.data() + __x.size(), __y.data());
}

With that fixed, it mostly simplifies... except that the new/delete itself doesn't go away.