Skip to content

Add move semantics to val<T> for class types - #277

Open
PhilippGrulich wants to merge 3 commits into
mainfrom
claude/investigate-val-std-semantics-6fUVX
Open

Add move semantics to val<T> for class types#277
PhilippGrulich wants to merge 3 commits into
mainfrom
claude/investigate-val-std-semantics-6fUVX

Conversation

@PhilippGrulich

Copy link
Copy Markdown
Member

Previously val for class types had only a copy constructor,
which forced an alloca + memcpy/copy_construct on every rvalue. NRVO
failures (e.g. multi-return functions) and explicit std::move(x) silently
fell back to deep copies.

Add a real move constructor and move assignment that transfer the
underlying alloca/heap pointer and a moved_ flag that suppresses the
source's traced destruct() call and heap free, so the resource is
released exactly once. Constrain the variadic-args constructor to
exclude same-type so the dedicated copy/move ctors always win in
overload resolution.

Tests cover move construction (trivial and non-trivial), move
assignment, self-move, ctor/dtor balance via a CountedDtor struct,
and return-by-value with both NRVO-friendly and conditional-return
paths. Static asserts verify nothrow move semantics.

Previously val<ValueType> for class types had only a copy constructor,
which forced an alloca + memcpy/copy_construct on every rvalue. NRVO
failures (e.g. multi-return functions) and explicit std::move(x) silently
fell back to deep copies.

Add a real move constructor and move assignment that transfer the
underlying alloca/heap pointer and a moved_ flag that suppresses the
source's traced destruct() call and heap free, so the resource is
released exactly once. Constrain the variadic-args constructor to
exclude same-type so the dedicated copy/move ctors always win in
overload resolution.

Tests cover move construction (trivial and non-trivial), move
assignment, self-move, ctor/dtor balance via a CountedDtor struct,
and return-by-value with both NRVO-friendly and conditional-return
paths. Static asserts verify nothrow move semantics.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tracing Benchmark

Details
Benchmark suite Current: c348f19 Previous: 10a6635 Ratio
exec_bc_addOne 36.6807 ns (± 1.64919) 37.3468 ns (± 8.00576) 0.98
exec_mlir_addOne 303.155 ns (± 9.34104) 258.029 ns (± 4.30464) 1.17
exec_cpp_addOne 3.90529 ns (± 0.846163) 3.6505 ns (± 0.452295) 1.07
exec_interpreted_addOne 38.3997 ns (± 1.64403) 38.3209 ns (± 4.07534) 1.00
comp_mlir_add 6.65752 ms (± 209.106) 5.52896 ms (± 150.264) 1.20
comp_mlir_ifThenElse 7.52157 ms (± 223.739) 6.15129 ms (± 143.859) 1.22
comp_mlir_deeplyNestedIfElse 6.26438 ms (± 257.847) 5.04123 ms (± 67.5269) 1.24
comp_mlir_loop 9.18899 ms (± 257.1) 7.23834 ms (± 348.192) 1.27
comp_mlir_ifInsideLoop 31.397 ms (± 450.092) 28.78 ms (± 822.48) 1.09
comp_mlir_loopDirectCall 14.2982 ms (± 239.606) 12.4205 ms (± 456.737) 1.15
comp_mlir_pointerLoop 30.254 ms (± 124.516) 28.18 ms (± 795.83) 1.07
comp_mlir_staticLoop 6.16367 ms (± 215.743) 4.98862 ms (± 45.2884) 1.24
comp_mlir_fibonacci 12.6686 ms (± 176.531) 10.5174 ms (± 254.747) 1.20
comp_mlir_gcd 11.2626 ms (± 182.85) 9.43739 ms (± 66.7206) 1.19
comp_mlir_nestedIf10 12.4785 ms (± 159.94) 10.9118 ms (± 562.598) 1.14
comp_mlir_nestedIf100 27.4398 ms (± 2.2828) 25.5045 ms (± 614.911) 1.08
comp_mlir_chainedIf10 11.9877 ms (± 157.301) 9.77351 ms (± 299.372) 1.23
comp_mlir_chainedIf100 22.9228 ms (± 244.475) 20.2026 ms (± 289.302) 1.13
comp_cpp_add 29.4674 ms (± 320.551) 25.3523 ms (± 536.121) 1.16
comp_cpp_ifThenElse 29.9561 ms (± 215.914) 25.6938 ms (± 472.16) 1.17
comp_cpp_deeplyNestedIfElse 31.2041 ms (± 206.136) 26.2772 ms (± 280.811) 1.19
comp_cpp_loop 30.1161 ms (± 177.083) 25.3249 ms (± 302.8) 1.19
comp_cpp_ifInsideLoop 32.4895 ms (± 4.77889) 26.0316 ms (± 253.783) 1.25
comp_cpp_loopDirectCall 30.6467 ms (± 189.113) 25.5171 ms (± 227.43) 1.20
comp_cpp_pointerLoop 30.8244 ms (± 195.128) 25.7051 ms (± 267.651) 1.20
comp_cpp_staticLoop 30.079 ms (± 301.997) 25.1416 ms (± 369.29) 1.20
comp_cpp_fibonacci 30.8963 ms (± 1.00737) 25.9456 ms (± 429.397) 1.19
comp_cpp_gcd 30.1578 ms (± 337.799) 25.3955 ms (± 444.048) 1.19
comp_cpp_nestedIf10 33.2888 ms (± 258.969) 28.4827 ms (± 851.989) 1.17
comp_cpp_nestedIf100 67.4103 ms (± 2.8987) 62.4417 ms (± 958.238) 1.08
comp_cpp_chainedIf10 35.8127 ms (± 650.659) 31.448 ms (± 927.552) 1.14
comp_cpp_chainedIf100 97.735 ms (± 599.963) 92.2053 ms (± 608.636) 1.06
comp_bc_add 14.5523 us (± 2.46773) 14.582 us (± 1.75527) 1.00
comp_bc_ifThenElse 16.9757 us (± 3.87851) 18.6811 us (± 3.58857) 0.91
comp_bc_deeplyNestedIfElse 20.1906 us (± 4.4203) 22.7163 us (± 4.31134) 0.89
comp_bc_loop 17.0116 us (± 3.82698) 18.9731 us (± 4.056) 0.90
comp_bc_ifInsideLoop 19.1749 us (± 4.07394) 21.2198 us (± 3.74251) 0.90
comp_bc_loopDirectCall 16.9648 us (± 3.71354) 18.9753 us (± 3.3135) 0.89
comp_bc_pointerLoop 17.962 us (± 3.75302) 20.1783 us (± 3.72759) 0.89
comp_bc_staticLoop 16.6423 us (± 3.46135) 17.3933 us (± 3.71277) 0.96
comp_bc_fibonacci 17.1275 us (± 4.45912) 18.4986 us (± 2.35865) 0.93
comp_bc_gcd 16.2905 us (± 2.58377) 17.9795 us (± 2.53701) 0.91
comp_bc_nestedIf10 31.312 us (± 4.64734) 34.8719 us (± 4.27966) 0.90
comp_bc_nestedIf100 197.904 us (± 10.3863) 191.397 us (± 12.8541) 1.03
comp_bc_chainedIf10 44.5023 us (± 9.42467) 49.1121 us (± 5.49462) 0.91
comp_bc_chainedIf100 326.771 us (± 14.1643) 297.447 us (± 12.8065) 1.10
comp_asmjit_add 17.922 us (± 5.02276) 20.7886 us (± 3.14001) 0.86
comp_asmjit_ifThenElse 27.4451 us (± 5.95218) 32.8265 us (± 5.22408) 0.84
comp_asmjit_deeplyNestedIfElse 49.1078 us (± 10.3235) 56.0766 us (± 9.15709) 0.88
comp_asmjit_loop 29.4295 us (± 5.70893) 35.0292 us (± 5.17887) 0.84
comp_asmjit_ifInsideLoop 49.246 us (± 11.1204) 57.2267 us (± 11.6151) 0.86
comp_asmjit_loopDirectCall 32.5169 us (± 5.7859) 44.056 us (± 5.42689) 0.74
comp_asmjit_pointerLoop 35.6107 us (± 6.00339) 48.1419 us (± 8.30256) 0.74
comp_asmjit_staticLoop 24.3038 us (± 4.96982) 28.3138 us (± 5.3941) 0.86
comp_asmjit_fibonacci 31.6513 us (± 6.02046) 43.0434 us (± 8.60098) 0.74
comp_asmjit_gcd 29.3456 us (± 5.84492) 35.0731 us (± 6.56689) 0.84
comp_asmjit_nestedIf10 98.2901 us (± 13.628) 104.565 us (± 14.2612) 0.94
comp_asmjit_nestedIf100 1075.95 us (± 18228.4) 1068.05 us (± 146903) 1.01
comp_asmjit_chainedIf10 150.59 us (± 16.3488) 154.231 us (± 15.4403) 0.98
comp_asmjit_chainedIf100 2.28894 ms (± 25.8592) 2.13529 ms (± 28.6135) 1.07
trace_add 2.27962 us (± 243.82) 2.49638 us (± 295.356) 0.91
completing_trace_add 2.27011 us (± 201.665) 2.4736 us (± 334.61) 0.92
trace_ifThenElse 8.38265 us (± 1.48178) 9.30328 us (± 1.67908) 0.90
completing_trace_ifThenElse 4.5841 us (± 560.73) 4.70958 us (± 574.319) 0.97
trace_deeplyNestedIfElse 25.431 us (± 6.11794) 26.0099 us (± 3.07346) 0.98
completing_trace_deeplyNestedIfElse 12.9767 us (± 2.27464) 13.1091 us (± 1.70257) 0.99
trace_loop 8.34233 us (± 1.41618) 8.71348 us (± 1.22788) 0.96
completing_trace_loop 4.72452 us (± 568.718) 4.77327 us (± 516.624) 0.99
trace_ifInsideLoop 16.3045 us (± 3.41567) 17.3334 us (± 2.90873) 0.94
completing_trace_ifInsideLoop 8.50969 us (± 1.33914) 8.82408 us (± 1.28846) 0.96
trace_loopDirectCall 8.51579 us (± 1.54073) 8.96005 us (± 1.49533) 0.95
completing_trace_loopDirectCall 4.72729 us (± 665.15) 5.1524 us (± 762.558) 0.92
trace_pointerLoop 13.8343 us (± 2.79313) 14.2471 us (± 2.16149) 0.97
completing_trace_pointerLoop 10.264 us (± 1.61819) 10.4746 us (± 1.84546) 0.98
trace_staticLoop 7.51429 us (± 934.839) 7.6142 us (± 1.0114) 0.99
completing_trace_staticLoop 7.43998 us (± 774.405) 7.46691 us (± 872.687) 1.00
trace_fibonacci 9.91118 us (± 1.93685) 10.1531 us (± 1.57566) 0.98
completing_trace_fibonacci 6.05382 us (± 949.561) 6.17947 us (± 858.737) 0.98
trace_gcd 7.57195 us (± 1.21147) 8.05058 us (± 1.02295) 0.94
completing_trace_gcd 3.89298 us (± 495.86) 4.06246 us (± 448.501) 0.96
trace_nestedIf10 40.4034 us (± 8.0849) 37.7878 us (± 6.23274) 1.07
completing_trace_nestedIf10 40.0172 us (± 7.861) 38.9354 us (± 7.34432) 1.03
trace_nestedIf100 1.50363 ms (± 32.1424) 1.34644 ms (± 53.7282) 1.12
completing_trace_nestedIf100 1.51145 ms (± 32.682) 1.35177 ms (± 56.6128) 1.12
trace_chainedIf10 97.9942 us (± 12.6066) 99.7738 us (± 12.6143) 0.98
completing_trace_chainedIf10 51.448 us (± 9.34201) 49.9159 us (± 9.0803) 1.03
trace_chainedIf100 4.48531 ms (± 92.4317) 4.48434 ms (± 79.2886) 1.00
completing_trace_chainedIf100 2.33602 ms (± 37.0324) 2.26925 ms (± 73.0211) 1.03
e2e_tiered_bc_to_mlir 45.7762 us (± 17.9026) 56.5271 us (± 14.5799) 0.81
e2e_single_mlir 7.04356 ms (± 158.116) 5.53847 ms (± 193.361) 1.27
tiered_compile_addOne 46.0516 us (± 16.6342) 55.7034 us (± 13.3607) 0.83
single_compile_mlir_addOne 3.79795 ms (± 147.733) 3.28567 ms (± 103.998) 1.16
single_compile_cpp_addOne 29.5067 ms (± 161.167) 25.0471 ms (± 510.067) 1.18
single_compile_bc_addOne 46.6153 us (± 16.9782) 56.0618 us (± 12.9099) 0.83
tiered_compile_sumLoop 64.773 us (± 20.5285) 77.4694 us (± 16.0654) 0.84
single_compile_mlir_sumLoop 6.13673 ms (± 177.091) 5.30892 ms (± 116.288) 1.16
single_compile_cpp_sumLoop 30.3831 ms (± 181.712) 25.7075 ms (± 518.009) 1.18
single_compile_bc_sumLoop 64.3333 us (± 18.0549) 77.1814 us (± 14.9321) 0.83
ir_add 713.108 ns (± 40.4354) 772.195 ns (± 71.3318) 0.92
ir_ifThenElse 1.49787 us (± 83.6574) 1.61196 us (± 182.266) 0.93
ir_deeplyNestedIfElse 3.28766 us (± 226.822) 3.38468 us (± 292.836) 0.97
ir_loop 1.55598 us (± 75.371) 1.65684 us (± 243.329) 0.94
ir_ifInsideLoop 2.75981 us (± 164.086) 2.89326 us (± 320.554) 0.95
ir_loopDirectCall 1.73049 us (± 119.649) 1.81889 us (± 168.556) 0.95
ir_pointerLoop 1.92079 us (± 157.685) 2.05088 us (± 272.65) 0.94
ir_staticLoop 1.41845 us (± 83.3022) 1.51351 us (± 200.357) 0.94
ir_fibonacci 1.6754 us (± 91.438) 1.77363 us (± 155.603) 0.94
ir_gcd 1.41406 us (± 86.433) 1.56065 us (± 170.558) 0.91
ir_nestedIf10 7.75785 us (± 497.784) 8.02456 us (± 1.15304) 0.97
ir_nestedIf100 90.9018 us (± 4.31277) 87.6189 us (± 6.58879) 1.04
ir_chainedIf10 11.7154 us (± 741.042) 11.6437 us (± 1.02792) 1.01
ir_chainedIf100 167.591 us (± 5.85271) 164.697 us (± 8.40094) 1.02
ssa_add 183.944 ns (± 10.6176) 204.202 ns (± 28.1667) 0.90
ssa_ifThenElse 434.501 ns (± 22.6209) 484.779 ns (± 51.85) 0.90
ssa_deeplyNestedIfElse 1.11647 us (± 71.2799) 1.20907 us (± 105.009) 0.92
ssa_loop 457.492 ns (± 24.4312) 533.363 ns (± 80.3068) 0.86
ssa_ifInsideLoop 864.099 ns (± 65.8921) 959.38 ns (± 91.9966) 0.90
ssa_loopDirectCall 463.803 ns (± 26.2942) 538.332 ns (± 83.9372) 0.86
ssa_pointerLoop 552.117 ns (± 26.5441) 612.761 ns (± 60.7414) 0.90
ssa_staticLoop 431.105 ns (± 21.6339) 475.509 ns (± 52.7257) 0.91
ssa_fibonacci 479.247 ns (± 29.221) 530.832 ns (± 47.7214) 0.90
ssa_gcd 420.656 ns (± 30.483) 468.824 ns (± 43.3429) 0.90
exec_mlir_add 12.4989 ns (± 1.13498) 10.7701 ns (± 1.25718) 1.16
exec_mlir_fibonacci 17.5517 us (± 1.80779) 13.3631 us (± 1.67729) 1.31
exec_mlir_sum 597.559 us (± 63.953) 513.173 us (± 15.8951) 1.16
exec_cpp_add 4.59301 ns (± 0.616091) 4.84074 ns (± 0.975486) 0.95
exec_cpp_fibonacci 109.307 us (± 8.79131) 97.148 us (± 14.5938) 1.13
exec_cpp_sum 23.7475 ms (± 1.10339) 35.9689 ms (± 194.582) 0.66
exec_bc_add 43.303 ns (± 2.69646) 43.5894 ns (± 5.2732) 0.99
exec_bc_fibonacci 623.521 us (± 11.7385) 753.817 us (± 16.9593) 0.83
exec_bc_sum 142.236 ms (± 4.78023) 163.437 ms (± 1.52509) 0.87
exec_asmjit_add 3.53821 ns (± 0.239277) 3.59554 ns (± 0.522867) 0.98
exec_asmjit_fibonacci 22.4047 us (± 1.92995) 20.7515 us (± 1.80854) 1.08
exec_asmjit_sum 5.29664 ms (± 33.1865) 4.84254 ms (± 26.3078) 1.09
exec_bc_add_noRegAlloc 43.3671 ns (± 2.63002) 44.3788 ns (± 6.39372) 0.98
exec_bc_add_regAlloc 43.3469 ns (± 4.72047) 43.9551 ns (± 5.99039) 0.99
exec_bc_fibonacci_noRegAlloc 629.585 us (± 11.007) 751.654 us (± 14.3443) 0.84
exec_bc_fibonacci_regAlloc 620.122 us (± 6.96616) 751.761 us (± 11.6866) 0.82
exec_bc_sum_noRegAlloc 148.526 ms (± 24.1712) 163.167 ms (± 446.848) 0.91
exec_bc_sum_regAlloc 141.558 ms (± 2.52588) 163.266 ms (± 1.17473) 0.87

This comment was automatically generated by workflow using github-action-benchmark.

claude added 2 commits May 10, 2026 08:06
The move ctor previously initialized value_ptr via val<T*>'s copy
constructor, which in tracing mode emits an extra traceCopy/ASSIGN
SSA op for what is logically just a pointer alias. Construct value_ptr
directly from the source's (raw pointer, TypedValueRef) so no IR op is
emitted for the move itself; only the source's refcount entry remains
in place via TypedValueRefHolder, which is purely host-side bookkeeping.

The new traces moveConstructTrivial and returnByValue lock in the
optimal IR (one ALLOCA, no traceCopy) so any future regression that
re-introduces the copy in the move path will fail the snapshot test.
…r val

Verifies the alloca count for a fully-unrolled static loop where each
iteration constructs a fresh val<Test> and copy-assigns it into a
val<Test> declared outside the loop. With three unrolled iterations
the IR has four allocas (one for outer plus one per iteration for
inner) and three memcpy calls for the copy-assignments; outer keeps
its single slot because copy-assignment writes through the existing
pointer rather than reallocating.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants