Çekirdek Çıtlatması (Bölüm III)
by faik, 08.09.06 at 9:25 pm :: Çekirdek :: permalink :: rss
Son olarak “asm” ve “c” volatile anahtar sözcüklerine bakalım. Özel olarak ikisi arasından_spesifikasyondaki tanımı ile_ “c” volatile günümüzde artık bir şey ifade etmiyor. Lkml’de son zamanlarda da çok tartışıldı. Biz de lkml ve gcc dokümanı ışığında bahsi geçen iki anahtar sözcüğün ne zaman ve nerelerde kullanılması gerektiğine bakalım.
Önce kullanımı daha bariz olan “asm” volatile:
Using the GNU Compiler Collection - Extended Asm bölümü içerisinden bir alıntı:
“If an asm has output operands, GCC assumes for optimization purposes the instruction has no side effects except to change the output operands. This does not mean instructions with a side effect cannot be used, but you must be careful, because the compiler may eliminate them if the output operands aren’t used, or move them out of loops, or replace two with one if they constitute a common subexpression. Also, if your instruction does have a side effect on a variable that otherwise appears not to change, the old value of the variable may be reused later if it happens to be found in a register.”
Özet ve örneklerle gcc asm blok’unuza şu optimizasyonları yapabilir:
(1) gcc, optimizasyon amaçlı bir komutun tek etkisinin _eğer tanımlı ise_ çıkış değerine olduğunu kabul eder. Ve bu değer bir yerde kullanılmıyorsa asm bloğunu kaldırabilir.
int Terminator(void)
{
int civil;
asm("addl $99, %0":"=c"(civil)::"%eax");
}
Terminator:
pushl %ebp
movl %esp, %ebp
popl %ebp
ret
int Terminator2(void)
{
int civil;
/* yeniden programlayarak artık yok etmemesi gerektiğini söyleyelim */
asm volatile("addl $99, %0":"=c"(civil));
}
Terminator2:
pushl %ebp
movl %esp, %ebp
#APP
addl $99, %ecx
#NO_APP
popl %ebp
ret
(2) gcc, inline asm blok’unu döngü içinde gereksiz yere çalışmasın diye dışarı çıkarabilir.
extern int globalwarming;
int report(void)
{
int dummy, co2;
for (co2 = 0; co2 < 100; co2++) {
globalwarming++;
asm("movl $666, %0":"=c"(dummy));
}
return dummy;
}
report:
pushl %ebp
#APP
movl $666, %ecx <—— döngü dışında
#NO_APP
movl %esp, %ebp
pushl %esi
movl globalwarming, %esi
pushl %ebx
movl $99, %eax
movl %ecx, %ebx
.p2align 4,,15
.L5:
leal 1(%esi), %edx
decl %eax
movl %edx, %esi
jns .L5
movl %edx, globalwarming
movl %ebx, %eax
popl %ebx
popl %esi
popl %ebp
ret
extern int globalwarming;
int report(void)
{
int dummy, co2;
for (co2 = 0; co2 < 100; co2++) {
globalwarming++;
asm volatile("movl $666, %0":"=c"(dummy));
}
return dummy;
}
report:
pushl %ebp
movl $99, %eax
movl %esp, %ebp
pushl %esi
movl globalwarming, %esi
pushl %ebx
.p2align 4,,15
.L5:
leal 1(%esi), %edx
movl %edx, %esi
#APP
movl $666, %ecx <——— döngü içinde
#NO_APP
decl %eax
jns .L5
popl %ebx
movl %ecx, %eax
movl %edx, globalwarming
popl %esi
popl %ebp
ret
(3) gcc, kod’da tekrarlanan kısımlardan birini elimine edip bir önceki’nin çıktısı’nı yeniden kullanabilir. (Common Subexpression Elimination(CSE))
Kodu C ile yazıp optimizasyonsuz ve -O2 ile derledikten sonra çıktılarda gcc cse etkisi görülebilir. Ama volatile’ın inline assembly üzerindeki etkisini görmek istiyoruz. Uğraştım, olmadı. C kodundan üretilen optimizasyonsuz kodu alarak, inline assembly haline çevirdim. Çıktı birebir aynı olacak şekilde, asm üzerinde oynadım ama yine -O2 ile derlediğimde optimize etmedi. Dokümantasyondaki ilgili kısım şu şekilde geçiyor: “replace two with one if they constitute a common subexpression”.
Ben de #gcc kanalına gidip sordum. Dokümanda geçen “replace two”; iki “common expression” değil, iki inline asm bloku anlamına geliyormuş. Dokümanda biraz daha iyi ifade edilebilir miydi acaba? ![]()
Buna tersten bakalım, önce volatile ile:
extern int a,b,c;
int testelimination()
{
asm volatile("movl %0, %1":"=r"(a):"r"(c));
asm volatile("movl %0, %1":"=r"(b):"r"(c));
}
testelimination:
pushl %ebp
movl %esp, %ebp
movl c, %eax
#APP
movl %eax, %eax
#NO_APP
movl %eax, a
movl c, %eax
#APP
movl %eax, %eax
#NO_APP
movl %eax, b
popl %ebp
ret
extern int a,b,c;
int testelimination()
{
asm("movl %0, %1":"=r"(a):"r"(c));
asm("movl %0, %1":"=r"(b):"r"(c));
}
testelimination:
pushl %ebp
movl c, %eax
movl %esp, %ebp
popl %ebp
#APP
movl %eax, %eax
#NO_APP
movl %eax, a
movl %eax, b
ret
“c” volatile son…


No comments at the moment.
Add a comment