or value types Swift only passes constant parameters to functions by value (not inout parameters but let's disregard that here). According to the language specification, the values are always "copied" but is that always true? Creating space on the stack and copy things on the stack for every little function including those that are in other modules, seems under optimized and will reduce performance.
In practice it is possible that value parameters can be passed under the hood as pointers, then the called function is responsible for copying the value if necessary. If that takes place I don't know. What exactly are the optimizations can we expect when passing by value?
The language specification describes how value semantics works; it does not describe how the compiled code achieves these semantics. In general, Swift guarantees nothing about how your code is optimized (although new ownership features will soon give users an increased degree of expressivity and control over this), but you can rest assured that the most obvious unnecessary copies are elided.
You can explore how code is actually compiled by using, well, a compiler explorer—be sure to set your language to Swift, and compile with the -O compiler flag.
Here are some more-or-less related topics you may wish to read more about to flesh out your understanding: value semantics, trivial types, copy-on-write, automatic reference counting, calling conventions, ownership.
Is there a reason that you're opening and closing multiple identical threads?
I tried to raise the question in compiler internals forum because I thought it might be better suited there. Then the thread appeared in the using swift forum, don't know what happened. You can delete the locked threads to make it more clean if you can.
Up to this point, we've left the exact mechanics of parameter passing underspecified, because generally we only care about the high-level semantics and want to leave the details up to the compiler to present value semantics in an efficient way. Concretely, for small values of concrete type (up to 3 machine registers in size) we pass and return those values in registers, and for larger values, or values of generic type, we pass them indirectly by pointer. Depending on the situation, the callee may "borrow" an immutable representation of the value, which can be shared between the caller and callee without making a copy, or the callee may "take" its own copy of the value, which it can move into place somewhere else; we generally use the "borrow" convention except in setters and initializers, since those two are the most likely places where we're likely to want to use an argument to form part of another value.
We're fleshing out more details of the parameter passing model, and providing user controls for it, in this feature pitch:
Thank you, this is the information I was after. In 99% of the cases programmers don't care how the parameters are passed, the only thing they care about is that it is done as efficiently as possible and let the compiler decide (just like you let the compiler decide inlining). Mostly FFI functions where you want to micro manage the parameter passing for example. This in contrast to older compiler languages where the parameter passing is more or less defined how define your functions/methods.