Skip to content

Suboptimal filling of plain struct with default member initializers #151512

@DymOK93

Description

@DymOK93

Consider creating a large plain struct with default member initializers (example taken from my NDA code and simplified to MRE):

struct IMemAllocator {
    virtual ~IMemAllocator() = default;
};

struct Data
{
	const void* p = nullptr;
	size_t sz = 0;
};

enum class HA : uint32_t 
{
	None = 0,
    Max = 2
};

enum class CA : uint32_t 
{
	None = 0,
    Max = 2
};

enum class Flags : uint32_t
{
	None = 0x0
};

struct Ctx
{
 	HA pha = HA::Max; 
	HA cha = HA::Max;
	CA ca = CA::Max;
	Flags flags = Flags::None;
	Data d1 = {}; 
	Data d2 = {};     
	Data d3 = {};
	Data d4 = {}; 
	Data d5 = {};  
	Data d6 = {}; 
	Data d7 = {}; 
};

struct Ctx2
{
	Data d1 = {};
	size_t count = 0;
	Data* pd1 = nullptr;
	Data* pd2 = nullptr;
	Data* pd3 = nullptr;
	IMemAllocator* pa = nullptr;
};

struct ACtx
{
	int id = 0;
	int indexes[12] = {0};
	int id2 = 0;
	bool f1 = false;
	bool f2 = false;
	bool f3 = false;
};

struct Data2
{
	bool f = false;
	std::byte h[32] = {};
};

struct State
{
	std::array<Ctx, 16> ctx = {};
	std::array<Ctx2, 16> ctx2 = {};
	std::array<ACtx, 24> actx = {};
	Data2 cache[2] = {};

	//
	//
	//
	State(IMemAllocator* pa)
	{
		for (uint32_t i = 0; i < 16; ++i)
			ctx2[i].pa = pa;
	}
};

For example, for x64, a bunch of mov/movups is generated, which looks less efficient than memset() and loop, as would be the case without initializers: https://gcc.godbolt.org/z/T6YvYrshd.
Performance comparison: https://quick-bench.com/q/OB0GiU3xV7iBpfweJxJy7uO9-w0

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions