Savijanje konstanti
<s>Savijanje konstanti i širenje konstantisu povezane optimizacije kompajlera koje mnogi moderni kompajleri.</s><s>Napredna forma širenja konstanti, poznata kao proređeno širenje konstanti, može mnogo preciynije da izvrši širenje konstanti i u isto vreme da uklanja mrtav kod.</s>

<s>Savijanje konstanti</s>

<s>Savijanje konstanti je proces prepoynavanja i izračunavanja konstantnih izraza za vreme prevođenja, a ne u vreme izvršavanja programa.</s><s>Termi u konstantnim izrazima su obično prosti literali, kao na primer celobrojni literal 2, ali, takođe, to mogu biti i promenljive čija se vrednost zna već za vreme prevođenja.</s><s>Razmotrimo sledeću naredbu:</s>

<s>i = 320 * 200 * 32;</s>

<s>Mnogi napredni prevodioci neće stvarno generisati dve instrukcije prevođenja i prostor za ovu naredbu.</s><s>Umesto toga, identifikovaće konstrukte poput ovih i zameniće izračunatu vrednost u vreme samog prevođenja.(u ovom slučaju, 2,048,000).</s><s>Rezultujući kod će učitati jednu već izračunatu vrednost, umesto učitavanja i množenja nekoliko vrednosti.</s>

<s>Savijanje konstanti može čak koristiti i aritmetičke identitete.</s><s>Kada je x celobrojnog tipa, vrednost izraza 0 * x je nula, čak iako prevodilac ne zna vrednost promenljive x.</s>

<s>Savijanje konstanti se ne primenjuje samo na brojeve.</s><s>Nadovezivanje (konkatenacija) stringovnih(nizova karaktera) literala i konstantnih nizova karaktera može biti savijeno u konstantu.</s><s>Kod poput ovog: "abc" + "def" može biti zamenjen kodom: "abcdef".</s>

<s>Savijanje konstanti može biti urađeno i u front-endu prevodioca na IR drvetu, koje predstavlja izvorni jezik višeg nivoa, pre nego što je preveden u  adresni kod drveta, ili u back endu, kao dodatak širenju konstanti.</s>

<s>Savijanje konstanti i cross prevodilac</s>

<s>Pri implementaciji cross prevodioca, mora se obezbediti da se ponašanje aritmetičkih operacija na host arhitekturi odgovara onoj na ciljnoj arhitekturi.</s><s>U suprotnom, ako dozvolimo savijanje konstanti, možemo, nesmotreno, promeniti ponašanje samog programa.</s><s>Ovo je od velikog značaja za operacije sa decimalnim zaretom, čija implemetacija može veoma da se razlikuje.</s>

<s>Širenje konstanti</s>

<s>Širenje konstanti proces zamene poznatih vrednosti nekih konstanti za vreme prevođenja.</s><s>Ove konstante uključuju one definisane iznad, kao i intrinsic funkcije primenjene na konstantne vrednosti.</s><s>Razmotrimo sledeći pseudokod:</s>

<s>int x = 14;
  int y = 7 - x / 2;
  return y * (28 / x + 2);</s>

<s>Širenje(propagacija) promenljive x čeka:</s>

<s>int x = 14;
  int y = 7 - 14 / 2;
  return y * (28 / 14 + 2);</s>

<s>Nastavak širenja zaustavlja i sledeći kod (koji bi dalje bio optimizovan putem uklanjanja mrtvog koda promenljivih x i y.)</s>

<s>int x = 14;
  int y = 0;
  return 0;</s>

<s>Širenje konstanti je u kompajleru predtsavljeno korišćenjem analiziranja rezultata dostupnih definicija.</s><s>Ako sve dostupne definicije jedne promenljive predstavljaju istu dodelu tj. dodeljuju istu vrednost konstante promenljivoj, tada promenljiva ima konstantnu vrednost i može biti zamenjena konstantom.</s><s>Širenje konstanti može uzrokovati i pojednostalvjivanje uslovnih grana, njihovom transformacijom u jendu ili više naredbi bez uslova, u slučaju kada uslovni izraz može biti izračunat u vreme prevođenja, kako bi se utvrdila njegova konačna vrednost.</s>

<s>Optimizacija na delu</s>

<s>Savijanje konstanti i njihovo širenje, najčešće su korišćene zajedno, kako bi se postiglo što više redukcija i uprošćavanja.</s><s>Iterativno ih koristimo, preklapajući ih, dok ni jedna izmena više ne bude moguća.</s><s>Razmotrimo sledeći pseudokod:</s>

<s>int a = 30;
  int b = 9 - (a / 5);
  int c;</s>

<s>c = b * 4;
  if (c > 10) {
     c = c - 10;
  }
  return c * (60 / a);</s>

<s>Primenjujemo širenje konstanti jednom, zatim savijamo konstante, nakon toga kod izgleda ovako:</s>

<s>int a = 30;
  int b = 3;
  int c;</s>

<s>c = b * 4;
  if (c > 10) {
     c = c - 10;
  }
  return c * 2;</s>

<s>Ponavljamo oba koraka dva puta, sledi rezultat:</s>

<s>int a = 30;
  int b = 3;
  int c;</s>

<s>c = 12;
  if (true) {
     c = 2;
  }
  return c * 2;</s>

<s>Kako su a i b uprošteni u konstante i njihove vrednosti zamenjene svuda gde su se pojavljivale, prevodilac sada primenjuje uklanjanje mrtvog koda kako bi ih odbacio i time dodatno uprostio kod :</s>

<s>int c;
  c = 12;</s>

<s>if (true) {
     c = 2;
  }
  return c * 2;
U kodu iznad, umesto True može stajati broj 1 ili bilo koja Boolean oznaka, zavisno od prevodioca.</s><s>Tradicionalnim širenjem konstanti, dobijamo samo ovoliku optimizaciju.</s><s>Ne možemo promeniti strukturu programa.</s>

<s>Postoji još jedna, slična, optimizacija, zvana proređeno širenje konstanti, koja bira odgovarajuću granu na osnovu if-condition. .</s><s>Prevodilac sada može da otkrije da će se if naredba izvršiti u true, c može biti eliminisana, kod se smanjuje još više:</s>

<s>return 4;</s>

<s>Ako bi ovaj pseudokod činio telo funkcije, prevodilac, dalje, može iskoristiti  informaciju o tome da će rezultat izvršavanja biti ceo broj4 kako bi uklonio nepotrebne pozive funkcije, rezultujući daljim poboljšanjem performansi.</s>

<s>Vidi još
 Control flow graph
 Use-define chain and SSA form
 Copy propagation
 Common subexpression elimination
 Partial evaluation</s>

<s>Reference</s>

<s>https://en.wikipedia.org/wiki/Constant_folding</s>

<s>Dalje čitanje</s>

<s>Informatika</s>

