digitalmars.D - Structs, Speed and refs.
- Jakob Bornecrantz (20/20) Oct 23 2012 Hey everybody!
- "Daniel =?UTF-8?B?S296w6FrIg==?= <kozzi11 gmail.com> (28/48) Oct 23 2012 Hi,
- Jakob Bornecrantz (44/71) Oct 23 2012 That doesn't seem to be the case, as at least DMD always copies
- martin (5/7) Oct 23 2012 And here we go again - missing rvalue-to-const-ref propagation.
Hey everybody! A bit of background; I'm porting some code over from D1 to D2 and I ran into a bit of a problem. I have a bunch of code that looks something like this: class Bar : Other { override void func(ref LargeStruct st) {} } Bar bar; LargeStruct foo, too; bar.func(foo - too); This compiles just fine in D1 but no longer in D2. Because the temp created by "foo - too" is not a lvalue apparently. I don't want to remove the "ref" storage type because i still want it to be fast. And I rather have neater looking code vs: LargeStruct foo, too, temp; temp = foo - too; bar.func(temp); One solution is to turn "in" structs into pass by reference, eg const ref, but not require lvalue semantics at the call site? Cheers, Jakob.
Oct 23 2012
Hi, First of all, I think there is no difference in speed between LargeStruct foo, too, temp; temp = foo - too; bar.func(temp); and with func without ref. How looks your opBinary(Right) method? For eg. this works for me: struct LargeStruct { int x; auto ref opBinary(string op)(LargeStruct rhs) if (op == "-") { this.x = this.x - rhs.x; return this; } } class Bar { void func(ref LargeStruct st) {} } void main(string[] args) { Bar bar = new Bar(); LargeStruct foo, too; bar.func(foo - too); } However this will modify foo struct. On Tuesday, 23 October 2012 at 09:44:06 UTC, Jakob Bornecrantz wrote:Hey everybody! A bit of background; I'm porting some code over from D1 to D2 and I ran into a bit of a problem. I have a bunch of code that looks something like this: class Bar : Other { override void func(ref LargeStruct st) {} } Bar bar; LargeStruct foo, too; bar.func(foo - too); This compiles just fine in D1 but no longer in D2. Because the temp created by "foo - too" is not a lvalue apparently. I don't want to remove the "ref" storage type because i still want it to be fast. And I rather have neater looking code vs: LargeStruct foo, too, temp; temp = foo - too; bar.func(temp); One solution is to turn "in" structs into pass by reference, eg const ref, but not require lvalue semantics at the call site? Cheers, Jakob.
Oct 23 2012
On Tuesday, 23 October 2012 at 10:36:11 UTC, Daniel Kozák wrote:Hi, First of all, I think there is no difference in speed between LargeStruct foo, too, temp; temp = foo - too; bar.func(temp); and with func without ref.That doesn't seem to be the case, as at least DMD always copies to the stack. Even if I change the function to have the struct as a unused local variable it still copies. void example(LargeStruct t, Bar bar) { bar.func(t); } with ref: Dump of assembler code for function _D7example4testFS7example11LargeStructC7example3BarZv: 0x0000000000425ee0 <+0>: push %rbp 0x0000000000425ee1 <+1>: mov %rsp,%rbp 0x0000000000425ee4 <+4>: sub $0x10,%rsp 0x0000000000425ee8 <+8>: lea 0x10(%rbp),%rsi 0x0000000000425eec <+12>: mov (%rdi),%rax 0x0000000000425eef <+15>: rex.W callq *0x30(%rax) 0x0000000000425ef3 <+19>: mov %rbp,%rsp 0x0000000000425ef6 <+22>: pop %rbp 0x0000000000425ef7 <+23>: retq without ref: Dump of assembler code for function _D7example4testFS7example11LargeStructC7example3BarZv: 0x0000000000425ee0 <+0>: push %rbp 0x0000000000425ee1 <+1>: mov %rsp,%rbp 0x0000000000425ee4 <+4>: sub $0x10,%rsp 0x0000000000425ee8 <+8>: lea 0x208(%rbp),%rsi 0x0000000000425eef <+15>: mov $0x40,%ecx 0x0000000000425ef4 <+20>: pushq (%rsi) 0x0000000000425ef6 <+22>: sub $0x8,%rsi 0x0000000000425efa <+26>: loop 0x425ef4 <_D7example4testFS7example11LargeStructC7example3BarZv+20> 0x0000000000425efc <+28>: mov (%rdi),%rax 0x0000000000425eff <+31>: rex.W callq *0x30(%rax) 0x0000000000425f03 <+35>: add $0x200,%rsp 0x0000000000425f0a <+42>: mov %rbp,%rsp 0x0000000000425f0d <+45>: pop %rbp 0x0000000000425f0e <+46>: retqHow looks your opBinary(Right) method? For eg. this works for me: struct LargeStruct { int x; auto ref opBinary(string op)(LargeStruct rhs) if (op == "-") { this.x = this.x - rhs.x; return this; } } class Bar { void func(ref LargeStruct st) {} } void main(string[] args) { Bar bar = new Bar(); LargeStruct foo, too; bar.func(foo - too); } However this will modify foo struct.Since this is D1 code being ported I'm currently using opSub. I tried changing your code to opSub and I got the same error as with mine. Your example should probably be an error. I'm not saying I was right in doing what I did. The point of the post was to improve D. Cheers, Jakob.
Oct 23 2012
On Tuesday, 23 October 2012 at 09:44:06 UTC, Jakob Bornecrantz wrote:One solution is to turn "in" structs into pass by reference, eg const ref, but not require lvalue semantics at the call site?And here we go again - missing rvalue-to-const-ref propagation. Check out http://forum.dlang.org/thread/yhnbcocwxnbutylfeoxi forum.dlang.org
Oct 23 2012