[Nemerle] Codegen quality
От: rameel https://github.com/rsdn/CodeJam
Дата: 02.03.17 10:02
Оценка: 72 (3)
Хочу на досуге поковыряться в кишках компилятора, а точнее в той ее части, что отвечает за кодогенерацию с целью улучшения качества выхлопа...

Например, можно начать с циклов. Сейчас вот для такого простейшего цикла
private Test(args: array[string]) : void
{
    unchecked
    {
        foreach (i in args)
            WriteLine(i);
    }
}


генерируется такой IL, на который не рассчитывает джит, в результате проверки за выход границы массива не устраняются. Не говоря уже о мелочах, таких как 2 инициалиазации переменной счетчика и использование более длинной инструкции callvirt instance int32 [mscorlib]System.Array::get_Length(), а не ldlen, что увеличивает размер метода. Для примера тот же самый код, сгенерированный C# имеет размер 25 байт против 38 у Nemerle.
  MSIL
    // Code size 38 (0x26)
    .maxstack 2
    .locals init (
        [0] int32,
        [1] string
    )

    IL_0000: ldc.i4.0
    IL_0001: stloc.0
    
    IL_0002: ldc.i4.0 // зачем-то 
    IL_0003: stloc.0
    
    // loop start (head: IL_0004)
        IL_0004: ldloc.0
        IL_0005: ldarg.0
        IL_0006: callvirt instance int32 [mscorlib]System.Array::get_Length()
        IL_000b: clt
        IL_000d: brfalse IL_0025

        IL_0012: ldarg.0
        IL_0013: ldloc.0
        IL_0014: ldelem.ref
        IL_0015: stloc.1
        IL_0016: ldloc.1
        IL_0017: call void [mscorlib]System.Console::WriteLine(string)
        IL_001c: ldloc.0
        IL_001d: ldc.i4.1
        IL_001e: add
        IL_001f: stloc.0
        IL_0020: br IL_0004
    // end loop

    IL_0025: ret

Для сравнения выхлоп джита для C#:
  ASM (C#)
00007FFBEBEE0494  xor         edi,edi  
00007FFBEBEE0496  mov         ebx,dword ptr [rsi+8]  
00007FFBEBEE0499  test        ebx,ebx  
00007FFBEBEE049B  jle         00007FFBEBEE04B0

start:
00007FFBEBEE049D  movsxd      rcx,edi  
00007FFBEBEE04A0  mov         rcx,qword ptr [rsi+rcx*8+10h]  
00007FFBEBEE04A5  call        00007FFC40CDDE80  
00007FFBEBEE04AA  inc         edi  
00007FFBEBEE04AC  cmp         ebx,edi  
00007FFBEBEE04AE  jg          start  

00007FFBEBEE04B0  add         rsp,20h 
                  ...
00007FFBEBEE04B7  ret

и Nemerle
  ASM (Nemerle)
00007FFBEBEC0493  xor         edi,edi

start:
00007FFBEBEC0495  mov         rcx,rsi  
00007FFBEBEC0498  cmp         dword ptr [rcx],ecx  
00007FFBEBEC049A  call        00007FFC4B4CCB40  
00007FFBEBEC049F  cmp         eax,edi  
00007FFBEBEC04A1  jle         00007FFBEBEC04BB  
00007FFBEBEC04A3  mov         ecx,dword ptr [rsi+8]  
00007FFBEBEC04A6  cmp         edi,ecx  
00007FFBEBEC04A8  jae         00007FFBEBEC04C2  
00007FFBEBEC04AA  movsxd      rcx,edi  
00007FFBEBEC04AD  mov         rcx,qword ptr [rsi+rcx*8+10h]  
00007FFBEBEC04B2  call        00007FFC40CDDE80  
00007FFBEBEC04B7  inc         edi  
00007FFBEBEC04B9  jmp         start  

00007FFBEBEC04BB  add         rsp,28h 
                  ...
00007FFBEBEC04C1  ret  

00007FFBEBEC04C2  call        00007FFC4B967BE0  
00007FFBEBEC04C7  int         3


В общем, код надо реорганизовать таким образом:
int i = 0;
goto start;

again:
        Console.WriteLine(args[i]);
        i = i + 1;

start:
        if (i < args.Length)
                goto again;


Теперь вопрос. Где копать и куда смотреть?

И главное. Я не могу открыть проект компилятора в студии. На все проекты пишет Load failed.
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.