July 10, 2022

Merhaba,

>

void example.loop1(): 203 - 127 = 76 satır
void example.loop2(): 237 - 203 = 34 satır
void example.loop3(): 285 - 237 = 48 satır
void example.loop4(): 330 - 285 = 45 satır
void example.loop5(): 386 - 330 = 56 satır

GodBolt bağlantısına bakılırsa DMD'nin çok az sayıda (binden az) satır assembly kodu ürettiği sonucu çıkıyor. Bunun sebebi belki de LDC'nin (2 bini aşkın satır!) gereksiz label&jump oluşturması. Örneğin loop1'de sadece 2 tane olan D'nin kendi etiketlemesini (D label statement) kullandığımızda ekstradan en az 5 tane daha oluşturuyor. Oysa tün döngü iki etiket (.LBB0_1 <- .LBB0_7) arasında gerçekleşiyor. Aradaki if/else için de etiket, jmp komutunun yazıldığı satırlar için bile başka etiketler...

Özetle bu testte, hem GDC (neredeyse 2 bin satır) hem de LDC'nin ürettiği sonuçlar kullanılmadı. Döngünün ürettiği sonucu doğrudan diziye yazdığı ve dizi üzerinde gezindiği için testin galibi foreach döngüsü (loop2), sonra while döngüsü (loop4x) geliyor.

Aslında test şartlarının tüm işlevler için eşit olması için global bir n dizisi kullanıldı ve ekrana yazmaktan kaçınıldı. Aynı sonucu veremediği için loop4x tasnif dışıdır, belki loop2 de öyle olabilir. Çünkü zaten o sırada dizide geziniyorken içeriğini değiştirmesi kolay olacaktır! 😀

Neyse, zaten temelde tek başına while ile do/while aynı şeylerdir. Ama bazı durumlar için ötekini diğerine tercih ederiz. Ancak testin 2. galibinin bir eksiği var: O da işaretli sayılarda çalışamaması. Çünkü kısa olması için döngüyü devam ettiren pozitiflik (0'dan büyük olma == true) kavramından yararlanıldı. Yani bir int dizimiz olsaydı ve döngüler eksili bir sayıdan başlasaydı for döngüsü kullanmak zorundaydık.

56 satır ile switch/case (loop5) bile tasnif dışı bırakılabilir çünkü loop1'deki gibi ekstra etiket kullanıldı. Yani bunlar (loop1 ve loop5) temelde bir döngü olmasalar da tekrar eden durumlarda yararlanılabilecek çok akıllı olanaklar. Zaten çoğu durumda assembly kodları yine cmp'ler ile dolu. Yani siz if de kullansanız switch/case de, kodu güzel ve kısa gösterme dışında assembly karşılıkları benzer. Üstelik etiket kullanarak birşeyler yapıyorsanız örneğin bir LDC'nin her şeyi başka etiketlerle ayırmasından dolayı gereksiz assembly kodu oluşuyor. Makine koduna çevirirken bu etiketler sadeleşiyor mu? İşte onu bilmiyorum...

// D Compiler v2.094.2
import std.stdio;

enum limit = 10;
uint[limit] n; // test array

void reset() {
     assert(n == [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]);/*
     n.writeln; //*/
     n = 0;
     n[0] = 1;
     assert(n == [1, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
     "-ok-".writeln;
}

void main()
{
     loop1(); // no prints
     reset(); // ASMcode: 76 lines

     loop2(); // foreach_reverse () { .. }
     reset(); // ASMcode: 34 lines

     loop3(); // for () { .. }
     reset(); // ASMcode: 48 lines

     loop4(); // do { .. } while();
     reset(); // ASMcode: 45 lines

     loop5(); // switch () { .. }
     reset(); // ASMcode: 56 lines

     loop4x(); // while () { .. }
}

void loop1()
{
  increment:
    n[0]++; // n = 1;

    if(n[0] < limit) {
      n[limit - n[0]] = n[0];
    } else
      goto print;
  goto increment;

  print:
    assert(n == [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]);
    __FUNCTION__.write(": ");
} // only 5 lines

void loop2()
{
  foreach_reverse (ref i; n) {
    i = n[0]++;
  }
  __FUNCTION__.write(": ");
} // only 3 lines

void loop3()
{
  for (; n[0] < limit; ++n[0]) {
    n[limit - n[0]] = n[0];
  }
  __FUNCTION__.write(": ");
} // only 3 lines

void loop4()
{
  do {
    n[limit - n[0]] = n[0];
  } while (++n[0] < limit);
  __FUNCTION__.write(": ");
} // only 3 lines

void loop5()
{
  outterloop: switch (n[0]) {
    case limit:
      break;
    default:
      n[limit - n[0]] = n[0]++;
      goto outterloop;
  }
  __FUNCTION__.write(": ");
} // only 5 lines

void loop4x()
{
  while (++n[0] < 10) {
    n[limit - n[0]] = n[0];
  } // [ 10, 9, 8, 7, 6, 5, 4, 3, 2, 0 ]
  __FUNCTION__.write(": ");
} // only 3 lines but wrong result

/* loop5test.d (10 July'22)
 * Programmer: SDB@79
 * Links: https://d.godbolt.org/z/no5xq7ohT
 */

Başarılar...