<html>
<head>
<style>
.hmmessage P
{
margin:0px;
padding:0px
}
body.hmmessage
{
FONT-SIZE: 10pt;
FONT-FAMILY:Tahoma
}
</style>
</head>
<body class='hmmessage'>backend.<BR>
I think it is correct, if inefficient.<BR>
 <BR>
 - Jay<BR><BR><BR>

<HR id=stopSpelling>
<BR>
> CC: m3devel@elegosoft.com<BR>> From: hosking@cs.purdue.edu<BR>> Subject: Re: [M3devel] code quality..<BR>> Date: Mon, 21 Jan 2008 11:01:52 -0500<BR>> To: jayk123@hotmail.com<BR>> <BR>> Is this having the front-end handle return of structs or the backend?<BR>> <BR>> On Jan 21, 2008, at 9:50 AM, Jay wrote:<BR>> <BR>> > Unoptimized code quality is really bad,<BR>> > even compared to unoptimized C, even compared<BR>> > to gcc, and optimized code quality isn't great.<BR>> ><BR>> > I have this made up C code. I was verifying<BR>> > the struct return calling convention.<BR>> ><BR>> > typedef struct {<BR>> > unsigned a;<BR>> > unsigned b;<BR>> > unsigned c;<BR>> > } d;<BR>> ><BR>> > d F2(unsigned a, unsigned b, unsigned c)<BR>> > {<BR>> > d e;<BR>> > e.a = a * b * c;<BR>> > e.b = 123;<BR>> > e.c = a - b - c;<BR>> > return e;<BR>> > }<BR>> ><BR>> > and then the equivalent Modula-3:<BR>> ><BR>> > INTERFACE T;<BR>> ><BR>> > TYPE T1 = RECORD<BR>> > a,b,c : INTEGER<BR>> > END;<BR>> ><BR>> > PROCEDURE F2(a,b,c : INTEGER) : T1;<BR>> ><BR>> > END T.<BR>> ><BR>> > MODULE T;<BR>> ><BR>> > PROCEDURE F2(a,b,c : INTEGER) : T1 =<BR>> > VAR<BR>> > e : T1;<BR>> > BEGIN<BR>> > e.a := (a * b * c);<BR>> > e.b := 123;<BR>> > e.c := (a - b - c);<BR>> > RETURN e;<BR>> > END F2;<BR>> ><BR>> > BEGIN<BR>> > END T.<BR>> ><BR>> > Unoptimized Visual C++ 8.0:<BR>> ><BR>> > _F2:<BR>> > 00000000: 55 push ebp<BR>> > 00000001: 8B EC mov ebp,esp<BR>> > 00000003: 83 EC 0C sub esp,0Ch<BR>> > 00000006: 8B 45 0C mov eax,dword ptr [ebp+0Ch]<BR>> > 00000009: 0F AF 45 10 imul eax,dword ptr [ebp+10h]<BR>> > 0000000D: 0F AF 45 14 imul eax,dword ptr [ebp+14h]<BR>> > 00000011: 89 45 F4 mov dword ptr [ebp-0Ch],eax<BR>> > 00000014: C7 45 F8 7B 00 00 mov dword ptr [ebp-8],7Bh<BR>> > 00<BR>> > 0000001B: 8B 4D 0C mov ecx,dword ptr [ebp+0Ch]<BR>> > 0000001E: 2B 4D 10 sub ecx,dword ptr [ebp+10h]<BR>> > 00000021: 2B 4D 14 sub ecx,dword ptr [ebp+14h]<BR>> > 00000024: 89 4D FC mov dword ptr [ebp-4],ecx<BR>> > 00000027: 8B 55 08 mov edx,dword ptr [ebp+8]<BR>> > 0000002A: 8B 45 F4 mov eax,dword ptr [ebp-0Ch]<BR>> > 0000002D: 89 02 mov dword ptr [edx],eax<BR>> > 0000002F: 8B 4D F8 mov ecx,dword ptr [ebp-8]<BR>> > 00000032: 89 4A 04 mov dword ptr [edx+4],ecx<BR>> > 00000035: 8B 45 FC mov eax,dword ptr [ebp-4]<BR>> > 00000038: 89 42 08 mov dword ptr [edx+8],eax<BR>> > 0000003B: 8B 45 08 mov eax,dword ptr [ebp+8]<BR>> > 0000003E: 8B E5 mov esp,ebp<BR>> > 00000040: 5D pop ebp<BR>> > 00000041: C3 ret<BR>> ><BR>> > Visual C++ 8.0 with /O1<BR>> ><BR>> > It writes the results right into the output.<BR>> > _F2:<BR>> > 00000000: 55 push ebp<BR>> > 00000001: 8B EC mov ebp,esp<BR>> > 00000003: 8B 4D 0C mov ecx,dword ptr [ebp+0Ch]<BR>> > 00000006: 8B 45 08 mov eax,dword ptr [ebp+8]<BR>> > 00000009: 8B D1 mov edx,ecx<BR>> > 0000000B: 0F AF 55 10 imul edx,dword ptr [ebp+10h]<BR>> > 0000000F: 0F AF 55 14 imul edx,dword ptr [ebp+14h]<BR>> > 00000013: 2B 4D 10 sub ecx,dword ptr [ebp+10h]<BR>> > 00000016: 89 10 mov dword ptr [eax],edx<BR>> > 00000018: 2B 4D 14 sub ecx,dword ptr [ebp+14h]<BR>> > 0000001B: C7 40 04 7B 00 00 mov dword ptr [eax+4],7Bh<BR>> > 00<BR>> > 00000022: 89 48 08 mov dword ptr [eax+8],ecx<BR>> > 00000025: 5D pop ebp<BR>> > 00000026: C3 ret<BR>> ><BR>> > with /O2<BR>> ><BR>> > _F2:<BR>> > 00000000: 8B 4C 24 08 mov ecx,dword ptr [esp+8]<BR>> > 00000004: 8B 54 24 0C mov edx,dword ptr [esp+0Ch]<BR>> > 00000008: 8B 44 24 04 mov eax,dword ptr [esp+4]<BR>> > 0000000C: 56 push esi<BR>> > 0000000D: 8B 74 24 14 mov esi,dword ptr [esp+14h]<BR>> > 00000011: 57 push edi<BR>> > 00000012: 8B F9 mov edi,ecx<BR>> > 00000014: 0F AF FA imul edi,edx<BR>> > 00000017: 0F AF FE imul edi,esi<BR>> > 0000001A: 2B CA sub ecx,edx<BR>> > 0000001C: 89 38 mov dword ptr [eax],edi<BR>> > 0000001E: 2B CE sub ecx,esi<BR>> > 00000020: 5F pop edi<BR>> > 00000021: C7 40 04 7B 00 00 mov dword ptr [eax+4],7Bh<BR>> > 00<BR>> > 00000028: 89 48 08 mov dword ptr [eax+8],ecx<BR>> > 0000002B: 5E pop esi<BR>> > 0000002C: C3 ret<BR>> ><BR>> > gcc 3.4.5 unoptimized<BR>> ><BR>> > _F2:<BR>> > 00000000: 55 push ebp<BR>> > 00000001: 89 E5 mov ebp,esp<BR>> > 00000003: 83 EC 18 sub esp,18h<BR>> > 00000006: 8B 4D 08 mov ecx,dword ptr [ebp+8]<BR>> > 00000009: 8B 45 0C mov eax,dword ptr [ebp+0Ch]<BR>> > 0000000C: 0F AF 45 10 imul eax,dword ptr [ebp+10h]<BR>> > 00000010: 0F AF 45 14 imul eax,dword ptr [ebp+14h]<BR>> > 00000014: 89 45 E8 mov dword ptr [ebp-18h],eax<BR>> > 00000017: C7 45 EC 7B 00 00 mov dword ptr [ebp-14h],7Bh<BR>> > 00<BR>> > 0000001E: 8B 55 10 mov edx,dword ptr [ebp+10h]<BR>> > 00000021: 8B 45 0C mov eax,dword ptr [ebp+0Ch]<BR>> > 00000024: 29 D0 sub eax,edx<BR>> > 00000026: 2B 45 14 sub eax,dword ptr [ebp+14h]<BR>> > 00000029: 89 45 F0 mov dword ptr [ebp-10h],eax<BR>> > 0000002C: 8B 45 E8 mov eax,dword ptr [ebp-18h]<BR>> > 0000002F: 89 01 mov dword ptr [ecx],eax<BR>> > 00000031: 8B 45 EC mov eax,dword ptr [ebp-14h]<BR>> > 00000034: 89 41 04 mov dword ptr [ecx+4],eax<BR>> > 00000037: 8B 45 F0 mov eax,dword ptr [ebp-10h]<BR>> > 0000003A: 89 41 08 mov dword ptr [ecx+8],eax<BR>> > 0000003D: 89 C8 mov eax,ecx<BR>> > 0000003F: C9 leave<BR>> > 00000040: C2 04 00 ret 4<BR>> > 00000043: 90 nop<BR>> > 00000044: 90 nop<BR>> > ...more nops for padding...<BR>> ><BR>> > gcc -O1<BR>> ><BR>> > _F2:<BR>> > 00000000: 55 push ebp<BR>> > 00000001: 89 E5 mov ebp,esp<BR>> > 00000003: 83 EC 18 sub esp,18h<BR>> > 00000006: 89 5D F8 mov dword ptr [ebp-8],ebx<BR>> > 00000009: 89 75 FC mov dword ptr [ebp-4],esi<BR>> > 0000000C: 8B 45 08 mov eax,dword ptr [ebp+8]<BR>> > 0000000F: 8B 4D 0C mov ecx,dword ptr [ebp+0Ch]<BR>> > 00000012: 8B 5D 10 mov ebx,dword ptr [ebp+10h]<BR>> > 00000015: 8B 75 14 mov esi,dword ptr [ebp+14h]<BR>> > 00000018: 89 CA mov edx,ecx<BR>> > 0000001A: 0F AF D3 imul edx,ebx<BR>> > 0000001D: 0F AF D6 imul edx,esi<BR>> > 00000020: 29 D9 sub ecx,ebx<BR>> > 00000022: 29 F1 sub ecx,esi<BR>> > 00000024: 89 10 mov dword ptr [eax],edx<BR>> > 00000026: C7 40 04 7B 00 00 mov dword ptr [eax+4],7Bh<BR>> > 00<BR>> > 0000002D: 89 48 08 mov dword ptr [eax+8],ecx<BR>> > 00000030: 8B 5D F8 mov ebx,dword ptr [ebp-8]<BR>> > 00000033: 8B 75 FC mov esi,dword ptr [ebp-4]<BR>> > 00000036: 89 EC mov esp,ebp<BR>> > 00000038: 5D pop ebp<BR>> > 00000039: C2 04 00 ret 4<BR>> > 0000003C: 90 nop<BR>> > 0000003D: 90 nop<BR>> > 0000003E: 90 nop<BR>> > 0000003F: 90 nop<BR>> ><BR>> > I didn't investigate all the switches much and simple -O vs. -O1 <BR>> > vs. -O2 vs. -o3<BR>> > all do the same.<BR>> ><BR>> > -O1 -fomit-frame-pointer netted:<BR>> ><BR>> > _F2:<BR>> > 00000000: 83 EC 1C sub esp,1Ch<BR>> > 00000003: 89 5C 24 14 mov dword ptr [esp+14h],ebx<BR>> > 00000007: 89 74 24 18 mov dword ptr [esp+18h],esi<BR>> > 0000000B: 8B 44 24 20 mov eax,dword ptr [esp+20h]<BR>> > 0000000F: 8B 4C 24 24 mov ecx,dword ptr [esp+24h]<BR>> > 00000013: 8B 5C 24 28 mov ebx,dword ptr [esp+28h]<BR>> > 00000017: 8B 74 24 2C mov esi,dword ptr [esp+2Ch]<BR>> > 0000001B: 89 CA mov edx,ecx<BR>> > 0000001D: 0F AF D3 imul edx,ebx<BR>> > 00000020: 0F AF D6 imul edx,esi<BR>> > 00000023: 29 D9 sub ecx,ebx<BR>> > 00000025: 29 F1 sub ecx,esi<BR>> > 00000027: 89 10 mov dword ptr [eax],edx<BR>> > 00000029: C7 40 04 7B 00 00 mov dword ptr [eax+4],7Bh<BR>> > 00<BR>> > 00000030: 89 48 08 mov dword ptr [eax+8],ecx<BR>> > 00000033: 8B 5C 24 14 mov ebx,dword ptr [esp+14h]<BR>> > 00000037: 8B 74 24 18 mov esi,dword ptr [esp+18h]<BR>> > 0000003B: 83 C4 1C add esp,1Ch<BR>> > 0000003E: C2 04 00 ret 4<BR>> > 00000041: 90 nop<BR>> > .. more nops ..<BR>> ><BR>> > Ok, ready, here goes the unoptimized Modula-3.<BR>> > Notice the duplicate copying of the return value and the *doubling* <BR>> > in code size.<BR>> ><BR>> > _T__F2:<BR>> > 00000000: 55 push ebp<BR>> > 00000001: 89 E5 mov ebp,esp<BR>> > 00000003: 57 push edi<BR>> > 00000004: 56 push esi<BR>> > 00000005: 83 EC 30 sub esp,30h<BR>> > 00000008: 8B 55 0C mov edx,dword ptr [ebp+0Ch]<BR>> > 0000000B: 8B 45 10 mov eax,dword ptr [ebp+10h]<BR>> > 0000000E: 0F AF D0 imul edx,eax<BR>> > 00000011: 8B 45 14 mov eax,dword ptr [ebp+14h]<BR>> > 00000014: 0F AF D0 imul edx,eax<BR>> > 00000017: 8B 45 D4 mov eax,dword ptr [ebp-2Ch]<BR>> > 0000001A: 83 E0 00 and eax,0<BR>> > 0000001D: 09 D0 or eax,edx<BR>> > 0000001F: 89 45 D4 mov dword ptr [ebp-2Ch],eax<BR>> > 00000022: 8B 45 D8 mov eax,dword ptr [ebp-28h]<BR>> > 00000025: 83 E0 00 and eax,0<BR>> > 00000028: 83 C8 7B or eax,7Bh<BR>> > 0000002B: 89 45 D8 mov dword ptr [ebp-28h],eax<BR>> > 0000002E: 8B 55 0C mov edx,dword ptr [ebp+0Ch]<BR>> > 00000031: 8B 45 10 mov eax,dword ptr [ebp+10h]<BR>> > 00000034: 29 C2 sub edx,eax<BR>> > 00000036: 8B 45 14 mov eax,dword ptr [ebp+14h]<BR>> > 00000039: 29 C2 sub edx,eax<BR>> > 0000003B: 8B 45 DC mov eax,dword ptr [ebp-24h]<BR>> > 0000003E: 83 E0 00 and eax,0<BR>> > 00000041: 09 D0 or eax,edx<BR>> > 00000043: 89 45 DC mov dword ptr [ebp-24h],eax<BR>> > 00000046: 8B 45 08 mov eax,dword ptr [ebp+8]<BR>> > 00000049: 89 C2 mov edx,eax<BR>> > 0000004B: 8D 45 D4 lea eax,[ebp-2Ch]<BR>> > 0000004E: 8D 7D EC lea edi,[ebp-14h]<BR>> > 00000051: 89 C6 mov esi,eax<BR>> > 00000053: FC cld<BR>> > 00000054: A5 movs dword ptr es:[edi],dword <BR>> > ptr [esi]<BR>> > 00000055: A5 movs dword ptr es:[edi],dword <BR>> > ptr [esi]<BR>> > 00000056: A5 movs dword ptr es:[edi],dword <BR>> > ptr [esi]<BR>> > 00000057: 89 D7 mov edi,edx<BR>> > 00000059: 8D 75 EC lea esi,[ebp-14h]<BR>> > 0000005C: FC cld<BR>> > 0000005D: A5 movs dword ptr es:[edi],dword <BR>> > ptr [esi]<BR>> > 0000005E: A5 movs dword ptr es:[edi],dword <BR>> > ptr [esi]<BR>> > 0000005F: A5 movs dword ptr es:[edi],dword <BR>> > ptr [esi]<BR>> > 00000060: 83 C4 30 add esp,30h<BR>> > 00000063: 5E pop esi<BR>> > 00000064: 5F pop edi<BR>> > 00000065: C9 leave<BR>> > 00000066: C3 ret<BR>> ><BR>> > optimized Modula-3 is better, saves the extra copy, but still not <BR>> > great:<BR>> ><BR>> > _T__F2:<BR>> > 00000000: 55 push ebp<BR>> > 00000001: 89 E5 mov ebp,esp<BR>> > 00000003: 57 push edi<BR>> > 00000004: 56 push esi<BR>> > 00000005: 53 push ebx<BR>> > 00000006: 83 EC 10 sub esp,10h<BR>> > 00000009: 8B 55 0C mov edx,dword ptr [ebp+0Ch]<BR>> > 0000000C: 8B 4D 10 mov ecx,dword ptr [ebp+10h]<BR>> > 0000000F: 8B 5D 14 mov ebx,dword ptr [ebp+14h]<BR>> > 00000012: 89 D0 mov eax,edx<BR>> > 00000014: 0F AF C1 imul eax,ecx<BR>> > 00000017: 0F AF C3 imul eax,ebx<BR>> > 0000001A: 8B 75 E8 mov esi,dword ptr [ebp-18h]<BR>> > 0000001D: 89 45 E8 mov dword ptr [ebp-18h],eax<BR>> > 00000020: 8B 45 EC mov eax,dword ptr [ebp-14h]<BR>> > 00000023: C7 45 EC 7B 00 00 mov dword ptr [ebp-14h],7Bh<BR>> > 00<BR>> > 0000002A: 29 CA sub edx,ecx<BR>> > 0000002C: 29 DA sub edx,ebx<BR>> ><BR>> > Huh what does this next instruction achieve?<BR>> > 0000002E: 8B 45 F0 mov eax,dword ptr [ebp-10h]<BR>> > 00000031: 89 55 F0 mov dword ptr [ebp-10h],edx<BR>> > 00000034: 8B 7D 08 mov edi,dword ptr [ebp+8]<BR>> > 00000037: 8D 75 E8 lea esi,[ebp-18h]<BR>> > 0000003A: FC cld<BR>> > 0000003B: A5 movs dword ptr es:[edi],dword <BR>> > ptr [esi]<BR>> > 0000003C: A5 movs dword ptr es:[edi],dword <BR>> > ptr [esi]<BR>> > 0000003D: A5 movs dword ptr es:[edi],dword <BR>> > ptr [esi]<BR>> > 0000003E: 83 C4 10 add esp,10h<BR>> > 00000041: 5B pop ebx<BR>> > 00000042: 5E pop esi<BR>> > 00000043: 5F pop edi<BR>> > 00000044: C9 leave<BR>> > 00000045: C3 ret<BR>> ><BR>> > and lastly the integrated backend, which runs much faster, and I <BR>> > believe has just one mode,<BR>> > somewhat optimized (but still lacks int64 support):<BR>> ><BR>> > _T__F2:<BR>> > 00000000: 55 push ebp<BR>> > 00000001: 8B EC mov ebp,esp<BR>> > 00000003: 81 EC 18 00 00 00 sub esp,18h<BR>> > 00000009: 53 push ebx<BR>> > 0000000A: 56 push esi<BR>> > 0000000B: 57 push edi<BR>> > 0000000C: 8B 5D 10 mov ebx,dword ptr [ebp+10h]<BR>> > 0000000F: 0F AF 5D 0C imul ebx,dword ptr [ebp+0Ch]<BR>> > 00000013: 0F AF 5D 14 imul ebx,dword ptr [ebp+14h]<BR>> > 00000017: 89 5D F4 mov dword ptr [ebp-0Ch],ebx<BR>> > 0000001A: C7 45 F8 7B 00 00 mov dword ptr [ebp-8],7Bh<BR>> > 00<BR>> > 00000021: 8B 55 0C mov edx,dword ptr [ebp+0Ch]<BR>> > 00000024: 2B 55 10 sub edx,dword ptr [ebp+10h]<BR>> > 00000027: 2B 55 14 sub edx,dword ptr [ebp+14h]<BR>> > 0000002A: 89 55 FC mov dword ptr [ebp-4],edx<BR>> > 0000002D: 8D 75 F4 lea esi,[ebp-0Ch]<BR>> > 00000030: 8B 7D 08 mov edi,dword ptr [ebp+8]<BR>> > 00000033: 8B 4E 00 mov ecx,dword ptr [esi]<BR>> > 00000036: 89 4F 00 mov dword ptr [edi],ecx<BR>> > 00000039: 8B 4E 04 mov ecx,dword ptr [esi+4]<BR>> > 0000003C: 89 4F 04 mov dword ptr [edi+4],ecx<BR>> > 0000003F: 8B 4E 08 mov ecx,dword ptr [esi+8]<BR>> > 00000042: 89 4F 08 mov dword ptr [edi+8],ecx<BR>> > 00000045: 8B C7 mov eax,edi<BR>> > 00000047: 5F pop edi<BR>> > 00000048: 5E pop esi<BR>> > 00000049: 5B pop ebx<BR>> > 0000004A: C9 leave<BR>> > 0000004B: C3 ret<BR>> ><BR>> > I haven't looked at all this in depth, but the doubling in size, <BR>> > the extra copy,<BR>> > that the integrated backend's code is fairly small...<BR>> ><BR>> > - Jay<BR>> ><BR>> > Shed those extra pounds with MSN and The Biggest Loser! Learn more.<BR>> <BR><BR><br /><hr />Connect and share in new ways with Windows Live. <a href='http://www.windowslive.com/share.html?ocid=TXT_TAGHM_Wave2_sharelife_012008' target='_new'>Get it now!</a></body>
</html>