The simple example #include <optional> std::optional<long> foo() { return 0; } shows suboptimal codegen at -O3 -std=c++17. The values seem to be forced through the stack. On AArch64 we get foo(): sub sp, sp, #16 mov w0, 1 strb w0, [sp, 8] mov x0, 0 ldr x1, [sp, 8] add sp, sp, 16 ret instead of (what clang gives) foo(): // @foo() mov w1, #1 mov x0, xzr ret On x86 it's the same: foo(): mov QWORD PTR [rsp-24], 0 mov rax, QWORD PTR [rsp-24] mov BYTE PTR [rsp-16], 1 mov rdx, QWORD PTR [rsp-16] ret vs foo(): // @foo() mov w1, #1 mov x0, xzr ret
last example for x86 should have been foo(): # @foo() xor eax, eax mov dl, 1 ret
Take: struct g { unsigned long b; }; struct a { struct g g1; unsigned char c; }; static inline void h(struct g *a) { a->b = 0; } static inline void j(struct a *a) { h(&a->g1); a->c = 1; } struct a f(void) { struct a a; j(&a); return a; } ---- CUT ---- It works, I suspect in the case of std::optional, std::optional is marked as BLKmode rather than TImode as the struct is marked as "ADDRESSABLE".
I think the issue is simply that RTL expansion forces the object to memory since that is what GIMPLE does: struct optional foo () { struct optional D.12374; <bb 2> [local count: 1073741824]: MEM <long int> [(struct optional *)&D.12374] = 0; MEM <unsigned char> [(struct optional *)&D.12374 + 8B] = 1; return D.12374; } and yes, if it would have had TImode we could expand it to a register pair but it has BLKmode because it's TYPE_NEEDS_CONSTRUCTING(?), the type isn't TREE_ADDRESSABLE for me.
(In reply to Richard Biener from comment #3) > and yes, if it would have had TImode we could expand it to a register pair > but it has BLKmode because it's TYPE_NEEDS_CONSTRUCTING(?), the type > isn't TREE_ADDRESSABLE for me. Yes TYPE_NEEDS_CONSTRUCTING, I had thought they were the same bit but I am wrong.
*** Bug 109631 has been marked as a duplicate of this bug. ***
Dup *** This bug has been marked as a duplicate of bug 95405 ***