[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>>
Re: [Nemerle] Codegen quality
От: VladD2 Российская Империя www.nemerle.org
Дата: 02.03.17 12:08
Оценка: 16 (1)
Здравствуйте, rameel, Вы писали:

R>Хочу на досуге поковыряться в кишках компилятора, а точнее в той ее части, что отвечает за кодогенерацию с целью улучшения качества выхлопа...


Хочу сразу предупредить, что многие косяки немерловой генерации нивелируются оптимизациями в джите. Например, практика показала, что бороться с лишними переменными совершенно бесполезно. Джит их сам отлично устраняет (а может они просто ложатся в регистры), так что на скорости кода это не сказывается.

Так что прежде чем что-то править, надо убедиться на тестах, что проблема реально существует.

R>private Test(args: array[string]) : void

R> foreach (i in args)

Учти, что foreach — это макрос. Так что "паттерн" для него генерируется не компилятором, а этим макросом. Находится он здесь.

Конкретно код для массивов генерируется здесь. Но там вроде как все цивильно:
        def one_dim_case()
        {
          def index = if(index != null) <[ $(index : name) ]> else <[ index ]>;
          def definition = build_definition(<[ cached_collection[$index] ]>);
          <[
            // accessing to Length property like here
            // should trigger CLR to enable "remove of array bounds checking" optimization
            for (mutable $index = 0; $index < cached_collection.Length; ++ $index)
              $definition;
          ]> :: []
        }


Так что смотреть надо, скорее, макрос for. Его код находится там же.

Конечно, возможно, что дело в генераторе кода, но с начало нужно в этом убедиться. Для этого надо посмотреть типизированное дерево. Для этого нужно поставить точку прерывания в методе Typer.RunSecondPass. Причем делать это нужно перед вызовом Typer2 и после каждого из шагов (на них производится переписывание кода). К этому моменту макросов уже не будет.

Для упрощения отладки надо выключить генерацию pdb, но не включать Release, иначе отладка будет невозможна.

Для подключения к компилятору проще всего создать проект немерла, описать в нем отлаживаемый код, расположить функцию с кодом первой в модуле, в свойствах проекта на закладке "Build" установить свойство "Run debugger" в true.

R>генерируется такой IL, на который не рассчитывает джит, в результате проверки за выход границы массива не устраняются.


А как ты смотрел ассемблер? Учти, что единственный достоверный способ проверить это — скомпилировать релизную версию и приатачиться к ней отладчиком во время выполнения (вызвать брэйк из кода). Сама программа должна при этом быть запущена без отладчика, иначе джит вырубет оптимизации. Ну, и далее надо смотреть ассемблер.

R>Не говоря уже о мелочах, таких как 2 инициалиазации переменной счетчика и использование более длинной инструкции callvirt instance int32 [mscorlib]System.Array::get_Length(), а не ldlen, что увеличивает размер метода.


Вот, кстати, это может и влиять на производительность. Возможно джит просто не делает оптимизации, так как видит вызов метода, а не эту инструкцию.

Но тут уже надо делать подмену вызова на инструкцию при генерации кода. Он находится в ILEmitter.n.

R>Для примера тот же самый код, сгенерированный C# имеет размер 25 байт против 38 у Nemerle.


Ну, сами по себе байты на скорость не влияют. Немерл генерит лишние переменные (особенно в дебаге), но их выкидывает джит.

R>В общем, код надо реорганизовать таким образом:

R>
R>int i = 0;
R>goto start;
R>again:
R>        Console.WriteLine(args[i]);
R>        i = i + 1;
R>start:
R>        if (i < args.Length)
R>                goto again;
R>


Ну, для foreach-а, можно конечно и прямо вот такое код сгенерировать. Но по уму нужно делать так, чтобы работал и "for" в который он переписывается.

Кстати, учти, что если в макросе используется макрос, то это макрос из старой версии макро-библиотеки (берущейся из бута). Так что просто поменять код макроса не выйдет. Нужно его бутсрапить (обновлять бут).

Я бы начал не с переписывания кода, а разобрался бы с заменой взова Length на инструкцию. Возможно джит ее и проверяет. Он не так туп и паттерн цикла долежен и так распозновать.

Делать оптимизацию для foreach-а особого смысла нет. Надо править макрос for. Сейчас там вот такой код:
      $init;
      ($("_N_break" : global) :
      {
        def loop() : void
        {
          when ($cond)
          {
            ($("_N_continue" : global) :
            {
              $body
            }) : void;
            $change;
            loop()
          }
        }

        loop();
      }) : void


Его надо заменить на нечто вроде:
using Nemerle.Imperative.GoTo; // нужно для использования макроса goto
...
    $init;
    ($("_N_break" : global) :
    {
    goto Start;
    label Next;
      ($("_N_continue" : global) :
      {
        $body
      }) : void;
      $change;
    label Start;
      when (i < args.Length)
        goto Next;
    }) : void


R>И главное. Я не могу открыть проект компилятора в студии. На все проекты пишет Load failed.


Это сделать не удастся. Сборка компилятора ведется из командной строки. Описание этого процесса — здесь.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: [Nemerle] Codegen quality
От: rameel https://github.com/rsdn/CodeJam
Дата: 02.03.17 12:12
Оценка:
Переписал с использованием goto , IL стал выглядеть почти как надо, но джиту не помогло. Мешает либо виртуальный вызов длины массива, либо callvirt instance int32 [mscorlib]System.Array::get_Length() хоть и инлайнится, но мешает оптимизации. Длина массива на каждой итерации грузится с памяти в регистр и сравнивается со счетчиком, плюс еще какое-то левое сравнение и вызов
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re[2]: [Nemerle] Codegen quality
От: fddima  
Дата: 02.03.17 12:41
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Ну, сами по себе байты на скорость не влияют. Немерл генерит лишние переменные (особенно в дебаге), но их выкидывает джит.

В общем случае ты не совсем прав: информация из CORINFO_METHOD_INFO (в том числе количество локальных переменных) может использоваться для вычисления рентабильности инлайнинга (для coreclr это DiscretionaryPolicy).
Ну про классику — на размер кода я думаю говорить не нужно, хотя по опять же EstimateCodeSize учитывает много вещей, в том числе и количество локалов. Поэтому безусловно лучше иметь минимально-оптимальный IL. Однако прям сейчас судя по конфигу — эти полиси по дефолту запрещены.
Re[2]: [Nemerle] Codegen quality
От: rameel https://github.com/rsdn/CodeJam
Дата: 02.03.17 13:01
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Хочу сразу предупредить, что многие косяки немерловой генерации нивелируются оптимизациями в джите. Например, практика показала, что бороться с лишними переменными совершенно бесполезно. Джит их сам отлично устраняет (а может они просто ложатся в регистры), так что на скорости кода это не сказывается.


Это да, но иногда может помешать джиту заинлайнить метод, так как одна из его эвристик смотрит на размер метода, который может оказаться выше некоего порога, и тогда джит пометит метод как [FAILED: too many il bytes] или как non profitable.

VD>Учти, что foreach — это макрос. Так что "паттерн" для него генерируется не компилятором, а этим макросом. Находится он здесь.

VD>Конкретно код для массивов генерируется здесь. Но там вроде как все цивильно:
VD>Так что смотреть надо, скорее, макрос for. Его код находится там же.

Ага, это я уже нашел и внимательно читаю.

VD>Конечно, возможно, что дело в генераторе кода, но с начало нужно в этом убедиться. Для этого надо посмотреть типизированное дерево <skipped>


ОК, спасибо, сейчас посмотрю.

VD>А как ты смотрел ассемблер? Учти, что единственный достоверный способ проверить это — скомпилировать релизную версию и приатачиться к ней отладчиком во время выполнения (вызвать брэйк из кода). Сама программа должна при этом быть запущена без отладчика, иначе джит вырубет оптимизации. Ну, и далее надо смотреть ассемблер.


Да, так и смотрел.

R>>Для примера тот же самый код, сгенерированный C# имеет размер 25 байт против 38 у Nemerle.

VD>Ну, сами по себе байты на скорость не влияют. Немерл генерит лишние переменные (особенно в дебаге), но их выкидывает джит.

Но, к сожалению, могут сказаться на выборе инлайнить или нет этот метод.

VD>Ну, для foreach-а, можно конечно и прямо вот такое код сгенерировать. Но по уму нужно делать так, чтобы работал и "for" в который он переписывается.


Да, надо именно for переписать.

VD>Кстати, учти, что если в макросе используется макрос, то это макрос из старой версии макро-библиотеки (берущейся из бута). Так что просто поменять код макроса не выйдет. Нужно его бутсрапить (обновлять бут).


VD>Я бы начал не с переписывания кода, а разобрался бы с заменой взова Length на инструкцию. Возможно джит ее и проверяет. Он не так туп и паттерн цикла долежен и так распозновать.


Когда я в последний раз смотрел на код джита, конкретно на место в котором определяется for-паттерн, то он там туп как пробка, ибо шаг влево, шаг вправо, и for он в лицо не узнает

Но я попробую сейчас протестировать немерловский IL с заменой Length, посмотрю, что выйдет. Потом уже и сам for можно будет переписать в if-do-while паттерн: Loop inversion, ибо джит не всегда почему-то это делает.
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re[3]: [Nemerle] Codegen quality
От: VladD2 Российская Империя www.nemerle.org
Дата: 02.03.17 13:02
Оценка:
Здравствуйте, fddima, Вы писали:

F> В общем случае ты не совсем прав: информация из CORINFO_METHOD_INFO (в том числе количество локальных переменных) может использоваться для вычисления рентабильности инлайнинга (для coreclr это DiscretionaryPolicy).

F> Ну про классику — на размер кода я думаю говорить не нужно, хотя по опять же EstimateCodeSize учитывает много вещей, в том числе и количество локалов. Поэтому безусловно лучше иметь минимально-оптимальный IL. Однако прям сейчас судя по конфигу — эти полиси по дефолту запрещены.

Конечно лучше быть здоровым и богатым, чем бедным и больным. И конечно лишние переменные это не блага.

Но я (и ни я один) делал множество тестов и разницы между Шаропом и Неменлом не видно в микроскоп. Даже в некоторых тестах Немерл вперед вырывается из-за косяков джита на которые нарывается шарповский компилятор и из-за того, что функциональный тип сделан в виде класса с более простой структурой. Но опять таки там разница не велика на сегодня.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: [Nemerle] Codegen quality
От: fddima  
Дата: 02.03.17 13:44
Оценка: +1
Здравствуйте, VladD2, Вы писали:

VD>Конечно лучше быть здоровым и богатым, чем бедным и больным. И конечно лишние переменные это не блага.

Я лишь показал что они могут попадать в оценки, хотя компилятор их и выкидывает. Более того — я не в курсе, обновляются ли оценки для уже скомпилированных методов. Что касается конкретных действий — то думаю ещё пару релизов net/coreclr можно смело не париться. А там... того глядишь и начнут оценивать иначе, например осилят AOT с profile-based кодогенерацией (мечты-мечты).

VD>Но я (и ни я один) делал множество тестов и разницы между Шаропом и Неменлом не видно в микроскоп. Даже в некоторых тестах Немерл вперед вырывается из-за косяков джита на которые нарывается шарповский компилятор и из-за того, что функциональный тип сделан в виде класса с более простой структурой. Но опять таки там разница не велика на сегодня.

С текущей политикой инлайнинга "лиж бы проперти аксессоры инлайнились" — он (инлайниг), и не может сильно влиять. В остальном же — IL/код вполне вменяемый — соответственно получаем закономерно нормальный результат. Остальное уже к TC, если ему не жалко времени на это.
Re[3]: [Nemerle] Codegen quality
От: rameel https://github.com/rsdn/CodeJam
Дата: 02.03.17 13:57
Оценка: 17 (2)
Здравствуйте, rameel, Вы писали:

R>Но я попробую сейчас протестировать немерловский IL с заменой Length, посмотрю, что выйдет.


Результаты теста:
1. Надо обязательно менять вызов Length на соответствующую инструкцию. Джит устранил проверки выхода за границы.
2. Надо реорганизовать цикл for и исправить последовательность инструкций, чтобы джит вытащил args.Length в регистры

IL_0024: ldlen

// вот эти 3 инструкции надо переписать в blt.s или в clt, brtrue.s
IL_0029: clt
IL_002b: brfalse IL_0035
IL_0030: br IL_0016


Попробую в качестве упражнения сделать.
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Отредактировано 02.03.2017 13:59 rameel . Предыдущая версия .
Re[2]: [Nemerle] Codegen quality
От: rameel https://github.com/rsdn/CodeJam
Дата: 02.03.17 17:09
Оценка:
Здравствуйте, VladD2, Вы писали:

    <[
      $init;

      ($("_N_break" : global) :
      {
        goto Start;

      label Next;
        ($("_N_continue" : global) :
        {
          $body
        }) : void;

        $change;

      label Start;
        when ($cond)
          goto Next;
      }) : void
    ]>


Как побороть ошибку FSM\DFSMTransform.n(198,9,229,10): error : Label 'Next' (12583) multiply defined ? Пытался по всякому, не работает.

PS. Кстати, а что случилось со статьями? Все листинги в статьях по немерле (остальные статьи не смотрел) слиплись в одну нечитаемую кашу
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Отредактировано 02.03.2017 17:43 rameel . Предыдущая версия .
Re[3]: [Nemerle] Codegen quality
От: WolfHound  
Дата: 02.03.17 17:54
Оценка: 18 (1)
Здравствуйте, rameel, Вы писали:

R>
R>    <[
R>      $init;

R>      ($("_N_break" : global) :
R>      {
R>        goto $start;

R>      label Next;
R>        ($("_N_continue" : global) :
R>        {
R>          $body
R>        }) : void;

R>        $change;

R>      label Start;
R>        when ($cond)
R>          goto $next;
R>      }) : void
R>    ]>
R>

Почему у тебя goto $next но при этом label Next?

Внутри реализации goto метки именуются тупо по именам.
Тут похоже Влад при реализации схалтурил. Нужно переделать таким образом, чтобы цвета имён тоже учитывались.
    private GetLabel(typer : Typer, name : string) : PExprLabel
    {
      def labelMap = GetLabelMap(typer);
      mutable @label;
      unless (labelMap.TryGetValue(name, out @label))
      {
        @label = PExprLabel(typer.Manager, name);
        labelMap[name] = @label;
      }
      @label
    }


В качестве временного решения должно сработать
    def start = Util.tmpname("start");
    def end   = Util.tmpname("end");
    <[
      $init;

      ($("_N_break" : global) :
      {
        goto $start;

      label $next;
        ($("_N_continue" : global) :
        {
          $body
        }) : void;

        $change;

      label $start;
        when ($cond)
          goto $next;
      }) : void
    ]>


R>Как побороть ошибку FSM\DFSMTransform.n(198,9,229,10): error : Label 'Next' (12583) multiply defined ? Пытался по всякому, не работает.

Интересно почему только с этим кодом проблема. Ибо у тебя должны ошибки по всему коду сыпаться.
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[4]: [Nemerle] Codegen quality
От: rameel https://github.com/rsdn/CodeJam
Дата: 02.03.17 18:19
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Почему у тебя goto $next но при этом label Next?


Остатки копипасты,я недостаточное количество раз Ctrl+Z нажал перед публикацией сюда А так я пробовал по разному

WH>Внутри реализации goto метки именуются тупо по именам.

WH>В качестве временного решения должно сработать
WH>
WH>    def start = Util.tmpname("start");
WH>    def end   = Util.tmpname("end");
WH>


Увы, так я тоже пробобовал. Ошибки в этом случае такие:
  Build Errors
"F:\Projects\nemerle\NemerleAll.nproj" (DevBuildQuick target) (1) ->
"F:\Projects\nemerle\snippets\peg-parser\Nemerle.Peg.Macros\Nemerle.Peg.Macros.nproj" (Build target) (10) ->
(CoreCompile target) ->
  AstUtils\CollectParseErrors.n(18,3,47,4): error : Expected simple name. [F:\Projects\nemerle\snippets\peg-parser\Nemerle.Peg.Macros\Nemerle.Peg.Macros.nproj]
  AstUtils\CollectParseErrors.n(18,3,47,4): error : Expected simple name. [F:\Projects\nemerle\snippets\peg-parser\Nemerle.Peg.Macros\Nemerle.Peg.Macros.nproj]
  AstUtils\CollectParseErrors.n(18,3,47,4): error : Expected simple name. [F:\Projects\nemerle\snippets\peg-parser\Nemerle.Peg.Macros\Nemerle.Peg.Macros.nproj]
  AstUtils\CollectParseErrors.n(18,3,47,4): error : Expected simple name. [F:\Projects\nemerle\snippets\peg-parser\Nemerle.Peg.Macros\Nemerle.Peg.Macros.nproj]
  FSM\DFSMTransform.n(123,9,151,10): error : Expected simple name. [F:\Projects\nemerle\snippets\peg-parser\Nemerle.Peg.Macros\Nemerle.Peg.Macros.nproj]
  FSM\DFSMTransform.n(123,9,151,10): error : Expected simple name. [F:\Projects\nemerle\snippets\peg-parser\Nemerle.Peg.Macros\Nemerle.Peg.Macros.nproj]
  FSM\DFSMTransform.n(123,9,151,10): error : Expected simple name. [F:\Projects\nemerle\snippets\peg-parser\Nemerle.Peg.Macros\Nemerle.Peg.Macros.nproj]
  FSM\DFSMTransform.n(123,9,151,10): error : Expected simple name. [F:\Projects\nemerle\snippets\peg-parser\Nemerle.Peg.Macros\Nemerle.Peg.Macros.nproj]
  FSM\DFSMTransform.n(175,7,176,33): error : Expected simple name. [F:\Projects\nemerle\snippets\peg-parser\Nemerle.Peg.Macros\Nemerle.Peg.Macros.nproj]
  FSM\DFSMTransform.n(175,7,176,33): error : Expected simple name. [F:\Projects\nemerle\snippets\peg-parser\Nemerle.Peg.Macros\Nemerle.Peg.Macros.nproj]
  FSM\DFSMTransform.n(175,7,176,33): error : Expected simple name. [F:\Projects\nemerle\snippets\peg-parser\Nemerle.Peg.Macros\Nemerle.Peg.Macros.nproj]
  FSM\DFSMTransform.n(175,7,176,33): error : Expected simple name. [F:\Projects\nemerle\snippets\peg-parser\Nemerle.Peg.Macros\Nemerle.Peg.Macros.nproj]
  FSM\DFSMTransform.n(198,9,229,10): error : Expected simple name. [F:\Projects\nemerle\snippets\peg-parser\Nemerle.Peg.Macros\Nemerle.Peg.Macros.nproj]
  FSM\DFSMTransform.n(198,9,229,10): error : Expected simple name. [F:\Projects\nemerle\snippets\peg-parser\Nemerle.Peg.Macros\Nemerle.Peg.Macros.nproj]
  FSM\DFSMTransform.n(198,9,229,10): error : Expected simple name. [F:\Projects\nemerle\snippets\peg-parser\Nemerle.Peg.Macros\Nemerle.Peg.Macros.nproj]
  FSM\DFSMTransform.n(198,9,229,10): error : Expected simple name. [F:\Projects\nemerle\snippets\peg-parser\Nemerle.Peg.Macros\Nemerle.Peg.Macros.nproj]
  Macro.n(17,3,19,4): error : Expected simple name. [F:\Projects\nemerle\snippets\peg-parser\Nemerle.Peg.Macros\Nemerle.Peg.Macros.nproj]
  Macro.n(17,3,19,4): error : Expected simple name. [F:\Projects\nemerle\snippets\peg-parser\Nemerle.Peg.Macros\Nemerle.Peg.Macros.nproj]
  Macro.n(17,3,19,4): error : Expected simple name. [F:\Projects\nemerle\snippets\peg-parser\Nemerle.Peg.Macros\Nemerle.Peg.Macros.nproj]
  Macro.n(17,3,19,4): error : Expected simple name. [F:\Projects\nemerle\snippets\peg-parser\Nemerle.Peg.Macros\Nemerle.Peg.Macros.nproj]
  Macro.n(40,3,66,4): error : Expected simple name. [F:\Projects\nemerle\snippets\peg-parser\Nemerle.Peg.Macros\Nemerle.Peg.Macros.nproj]
  Macro.n(40,3,66,4): error : Expected simple name. [F:\Projects\nemerle\snippets\peg-parser\Nemerle.Peg.Macros\Nemerle.Peg.Macros.nproj]
  Macro.n(40,3,66,4): error : Expected simple name. [F:\Projects\nemerle\snippets\peg-parser\Nemerle.Peg.Macros\Nemerle.Peg.Macros.nproj]
  Macro.n(40,3,66,4): error : Expected simple name. [F:\Projects\nemerle\snippets\peg-parser\Nemerle.Peg.Macros\Nemerle.Peg.Macros.nproj]
  AstUtils\ValidateAst.n(18,3,78,4): error : Expected simple name. [F:\Projects\nemerle\snippets\peg-parser\Nemerle.Peg.Macros\Nemerle.Peg.Macros.nproj]
  AstUtils\ValidateAst.n(18,3,78,4): error : Expected simple name. [F:\Projects\nemerle\snippets\peg-parser\Nemerle.Peg.Macros\Nemerle.Peg.Macros.nproj]
  AstUtils\ValidateAst.n(18,3,78,4): error : Expected simple name. [F:\Projects\nemerle\snippets\peg-parser\Nemerle.Peg.Macros\Nemerle.Peg.Macros.nproj]
  AstUtils\ValidateAst.n(18,3,78,4): error : Expected simple name. [F:\Projects\nemerle\snippets\peg-parser\Nemerle.Peg.Macros\Nemerle.Peg.Macros.nproj]
  RangeSets.n(23,7,32,8): error : Expected simple name. [F:\Projects\nemerle\snippets\peg-parser\Nemerle.Peg.Macros\Nemerle.Peg.Macros.nproj]
  RangeSets.n(23,7,32,8): error : Expected simple name. [F:\Projects\nemerle\snippets\peg-parser\Nemerle.Peg.Macros\Nemerle.Peg.Macros.nproj]
  RangeSets.n(23,7,32,8): error : Expected simple name. [F:\Projects\nemerle\snippets\peg-parser\Nemerle.Peg.Macros\Nemerle.Peg.Macros.nproj]
  RangeSets.n(23,7,32,8): error : Expected simple name. [F:\Projects\nemerle\snippets\peg-parser\Nemerle.Peg.Macros\Nemerle.Peg.Macros.nproj]
  Util.n(58,5,60,6): error : Expected simple name. [F:\Projects\nemerle\snippets\peg-parser\Nemerle.Peg.Macros\Nemerle.Peg.Macros.nproj]
  Util.n(58,5,60,6): error : Expected simple name. [F:\Projects\nemerle\snippets\peg-parser\Nemerle.Peg.Macros\Nemerle.Peg.Macros.nproj]
  Util.n(58,5,60,6): error : Expected simple name. [F:\Projects\nemerle\snippets\peg-parser\Nemerle.Peg.Macros\Nemerle.Peg.Macros.nproj]
  Util.n(58,5,60,6): error : Expected simple name. [F:\Projects\nemerle\snippets\peg-parser\Nemerle.Peg.Macros\Nemerle.Peg.Macros.nproj]
  Util.n(64,5,66,6): error : Expected simple name. [F:\Projects\nemerle\snippets\peg-parser\Nemerle.Peg.Macros\Nemerle.Peg.Macros.nproj]
  Util.n(64,5,66,6): error : Expected simple name. [F:\Projects\nemerle\snippets\peg-parser\Nemerle.Peg.Macros\Nemerle.Peg.Macros.nproj]
  Util.n(64,5,66,6): error : Expected simple name. [F:\Projects\nemerle\snippets\peg-parser\Nemerle.Peg.Macros\Nemerle.Peg.Macros.nproj]
  Util.n(64,5,66,6): error : Expected simple name. [F:\Projects\nemerle\snippets\peg-parser\Nemerle.Peg.Macros\Nemerle.Peg.Macros.nproj]


R>>Как побороть ошибку FSM\DFSMTransform.n(198,9,229,10): error : Label 'Next' (12583) multiply defined ? Пытался по всякому, не работает.

WH>Интересно почему только с этим кодом проблема. Ибо у тебя должны ошибки по всему коду сыпаться.

В разных случаях по разному, в основном компиляция заканчивается проекте peg-parser
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re[3]: [Nemerle] Codegen quality
От: VladD2 Российская Империя www.nemerle.org
Дата: 02.03.17 18:20
Оценка: 18 (1)
Здравствуйте, rameel, Вы писали:

R>Как побороть ошибку FSM\DFSMTransform.n(198,9,229,10): error : Label 'Next' (12583) multiply defined ? Пытался по всякому, не работает.


Косяк в label-макре. Очень уж редко это дело используется. По сути всего один раз использовали в Нитре. Они там по именам в хэш-таблицу загоняются.

Вот так должно помочь:
    def startLabelName = Util.tmpname("StartLabel");
    def nextLabelName  = Util.tmpname("NextLabel");

    <[
      $init;

      ($("_N_break" : global) :
      {
        goto $(startLabelName : usesite);

      label $(nextLabelName : usesite);
        ($("_N_continue" : global) :
        {
          $body
        }) : void;

        $change;

      label $(startLabelName : usesite);
        when ($cond)
          goto $(nextLabelName : usesite);
      }) : void
    ]>


Т.е. вручную сгенерировать уникальные имена для лэйблов.

R>PS. Кстати, а что случилось со статьями? Все листинги в статьях по немерле (остальные статьи не смотрел) слиплись в одну нечитаемую кашу


Я вижу, что первый отступ улетает. А так вроде читабельно
Автор(ы): Чистяков Владислав Юрьевич
Дата: 20.02.2012
Данная часть посвящена синтаксису Nemerle.
.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Отредактировано 02.03.2017 18:52 VladD2 . Предыдущая версия .
Re[4]: [Nemerle] Codegen quality
От: rameel https://github.com/rsdn/CodeJam
Дата: 02.03.17 18:32
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Вот так должно помочь:

VD>Т.е. вручную сгенерировать уникальные имена для лэйблов.

Работает
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re[4]: [Nemerle] Codegen quality
От: rameel https://github.com/rsdn/CodeJam
Дата: 02.03.17 18:35
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Я вижу, что первый отступ улетает. А так вроде читабельно
Автор(ы): Чистяков Владислав Юрьевич
Дата: 20.02.2012
Данная часть посвящена синтаксису Nemerle.
.


Вот здесь например Язык Nemerle. Часть 5
Автор(ы): Чистяков Владислав Юрьевич
Дата: 22.09.2011
Данная часть посвящена макросам Nemerle.
с середины статьи листинг Disposable_BeforeTypedMembers.n, и такое часто, просто где-то это не мешает, а где то, вот как здесь — не читаемо совсем
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re[5]: [Nemerle] Codegen quality
От: VladD2 Российская Империя www.nemerle.org
Дата: 02.03.17 18:46
Оценка:
Здравствуйте, rameel, Вы писали:

R>Вот здесь например Язык Nemerle. Часть 5
Автор(ы): Чистяков Владислав Юрьевич
Дата: 22.09.2011
Данная часть посвящена макросам Nemerle.
с середины статьи листинг Disposable_BeforeTypedMembers.n, и такое часто, просто где-то это не мешает, а где то, вот как здесь — не читаемо совсем


Да, что-то не так. И первые строки в листингах постоянно убегают вперед.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: [Nemerle] Codegen quality
От: VladD2 Российская Империя www.nemerle.org
Дата: 02.03.17 19:42
Оценка:
Здравствуйте, rameel, Вы писали:

R>Работает


Я тут этот вариант попробовал, и оказалось не все так радужно как на первый взгляд. При компиляции не тривиальных циклов (в Нитре, например) вылазит сообщение о нелокальном goto в выражениях.

Так что это дело надо как следует тестировать.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: [Nemerle] Codegen quality
От: rameel https://github.com/rsdn/CodeJam
Дата: 02.03.17 19:45
Оценка: 183 (2)
Здравствуйте, rameel, Вы писали:

Результы изменений: джит полностью устранил проверку выхода за границу массива, проверку на null и вызов чего-то там на каждой итерации цикла
Before:  1605 ms,  ips:    622 993,61
 After:   329 ms,  ips:  3 031 065,39


5 кратное ускорение на простом цикле

def ary = array(1000);
            
Measure("After", () => {
    def a = ary;
    mutable s = 0;
    
    unchecked {
        for (mutable i = 0; i < 1_000_000; i++)
            foreach (v in a)
                s += v;

        s;
    }
});


Кстати, перед тем как отправить пуллреквест, хочу спросить. Я в методе emit_method_call добавил такое условие:
      else if (method.DeclaringType == typeof(Array) && method.Name == "get_Length")
      {
        _ilg.Emit(OpCodes.Ldlen);
        _ilg.Emit(OpCodes.Conv_I4);
      }


Так в проекте делается или надо каким-то образом немерлевские метаданные проверять?
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re[6]: [Nemerle] Codegen quality
От: rameel https://github.com/rsdn/CodeJam
Дата: 02.03.17 20:01
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Я тут этот вариант попробовал, и оказалось не все так радужно как на первый взгляд. При компиляции не тривиальных циклов (в Нитре, например) вылазит сообщение о нелокальном goto в выражениях.


У меня проект нитры скомпилировался только с такими сообщениями:
Build succeeded.

"F:\Projects\nitra\Common\BootTasks.proj" (BuildBoot target) (1) ->
"F:\Projects\nitra\Boot2\Nitra.Compiler\Nitra.Compiler.nproj" (Build target) (2) ->
"F:\Projects\nitra\Boot2\Nitra.Runtime\Nitra.Runtime.nproj" (default target) (3) ->
(CoreCompile target) ->
  Parsing\ParseResult.n(45,131,45,135): warning : N168: a function parameter head was never used (defined in '.ctor(par
seSession : Nitra.ParseSession, sourceSnapshot : Nitra.SourceSnapshot, oldParseResult : Nitra.ParseResult, head : int,
tail : int) : void') [F:\Projects\nitra\Boot2\Nitra.Runtime\Nitra.Runtime.nproj]
  Parsing\ParseResult.n(45,131,45,135): warning : hint: replace name with `_' or prefix it like `_bar' to avoid the war
ning [F:\Projects\nitra\Boot2\Nitra.Runtime\Nitra.Runtime.nproj]

    2 Warning(s)
    0 Error(s)


Или имеется в виду, что сообщения вылезли при компиляции одной из грамматик нитры?
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re[6]: [Nemerle] Codegen quality
От: rameel https://github.com/rsdn/CodeJam
Дата: 02.03.17 20:18
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Я тут этот вариант попробовал, и оказалось не все так радужно как на первый взгляд. При компиляции не тривиальных циклов (в Нитре, например) вылазит сообщение о нелокальном goto в выражениях.


Хорошо бы понять почему так происходит, но у меня пока не хватает знаний по внутренностям компилятора, поэтому можно пока цикл for оставить как и раньше, так как джит вполне справился, остались только один 2 джампа, вместо одно на итерацию, но это мелочи. С этим можно и потом разобраться.

00007FFBEBED0BE5  xor         eax,eax  
00007FFBEBED0BE7  mov         edx,dword ptr [rsi+8]  

00007FFBEBED0BEA  cmp         edx,eax  
00007FFBEBED0BEC  jle         00007FFBEBED0BFB  
00007FFBEBED0BEE  movsxd      rcx,eax  
00007FFBEBED0BF1  mov         ecx,dword ptr [rsi+rcx*4+10h]  
00007FFBEBED0BF5  add         edi,ecx  
00007FFBEBED0BF7  inc         eax  
00007FFBEBED0BF9  jmp         00007FFBEBED0BEA
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re[7]: [Nemerle] Codegen quality
От: VladD2 Российская Империя www.nemerle.org
Дата: 02.03.17 20:31
Оценка:
Здравствуйте, rameel, Вы писали:

R>Или имеется в виду, что сообщения вылезли при компиляции одной из грамматик нитры?


Сейчас уже не помню. Мне кажется на одном из первых проектов вылезло. Ну, может я что-то накосячил.

Ты какую ветку Нитры собираешь?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.