Write-After-Read Hazard — keyingi buyruq registr yoki xotiraga yangi qiymatni oldingi buyruq eski qiymatni o‘qib ulgurishidan avval yozishi mumkin bo‘lgan nom bog‘liqligidir. WAR anti-dependency deb ham ataladi. U qiymat ishlab chiqaruvchi-iste’molchi oqimini emas, bir saqlash nomining turli davrdagi ishlatilishini aks ettiradi.
Registr misoli
SUB r4, r1, r5
ADD r1, r2, r3
Birinchi buyruq r1ning eski qiymatini o‘qishi, ikkinchisi keyin yangi qiymat yozishi kerak. In-order pipeline’da register read oldin, write-back dastur tartibida keyin bo‘lsa WAR o‘z-o‘zidan yuz bermaydi. Out-of-order execution’da ADD erta tugab, umumiy arxitektura katagiga yozsa SUB noto‘g‘ri yangi qiymatni olishi mumkin.
Register renaming
Rename mantiqi ADD natijasi uchun yangi Physical Register ajratadi. SUB decode qilingan paytdagi eski r1 tegini saqlaydi, ADD esa yangi tegga yozadi. Shu bilan ikkala amal parallel bajarilishi mumkin va WAR cheklovi yo‘qoladi. Commit keyin arxitektura r1 nomini yangi versiyaga rasmiy bog‘laydi.
Predicate, condition code va partial register ham rename qilinmasa WAR yaratishi mumkin. Yangi kichik yozuv eski yuqori bitni saqlasa, u faqat nom bog‘liqligi emas, haqiqiy merge dependencyga aylanishi ehtimol.
Xotiradagi anti-dependency
Compiler load’ni keyingi store’dan oldin saqlashi kerak, agar manzillar bir xil bo‘lishi mumkin bo‘lsa. Alias analysis obyektlar alohida ekanini isbotlasa store oldinga ko‘chirilishi mumkin. Aks holda yangi qiymat load ko‘rishi kerak bo‘lgan eski ma’lumotni bosib yuboradi.
Protsessor xotiraga fizik yozuvni Store Queue va commit orqali kechiktiradi. Eski load manzili hamda bajarilishi tekshirilmasdan yosh store tashqi ko‘rinadigan bo‘lmaydi. Xotira versiyalash registr renaming’dan murakkab, chunki manzil soni katta va dinamik.
Rejalashtirishdagi ahamiyati
Compiler register allocation vaqtinchalik qiymatlarga bir xil arxitektura registrini qayta ishlatib, sun’iy WAR qirralari yaratishi mumkin. Ko‘proq registr mavjud bo‘lsa live range’lar alohida nomlanadi. Juda ko‘p vaqtinchalik qiymat esa register pressure va spill keltiradi.
WAR’ni RAW bilan aralashtirmaslik kerak. RAW’da keyingi o‘quvchi yangi natijani kutishi shart va renaming uni olib tashlamaydi. WAR’da oldingi o‘quvchi eski versiyani oladi; yangi yozuvni boshqa fizik joyga yo‘naltirish yetarli.
Misoliy scheduling
Anti-dependency compiler instruction scheduling’da mustaqil amalni oldinga ko‘chirishga to‘sqinlik qilishi mumkin. Register renamer apparatda buni dinamik hal qiladi, compiler esa virtual registrlar va Static Single Assignment ko‘rinishida har ta’rifga alohida nom berib, keyin fizik arxitektura registrlarini taqsimlaydi.
Register allocation bosqichida bir xil rangga berilgan live range’lar bir-biriga ustma-ust tushmasligi kerak. Noto‘g‘ri liveness tahlili yangi yozuvni eski o‘qishdan oldin joylashtiradi. Debug build’da optimallashtirish kam bo‘lsa ko‘proq xotira spill ishlatilishi, release build’da esa register reuse va scheduling kuchliroq bo‘lishi mumkin.
Xotira operandlarida WAR xavfi alias tahliliga bog‘liq. Avvalgi load o‘qib ulgurmasdan keyingi store shu manzilga yozsa natija buziladi. Apparatura load queue orqali tartibni kuzatadi; compiler esa pointerlar mustaqilligini isbotlay olmasa ehtiyotkor ketma-ketlikni saqlaydi.
Out-of-order yadroda o‘qish odatda fizik manba registridan bajariladi, keyingi yozuv esa yangi fizik destination oladi. Shuning uchun arxitektura nomi bir xil bo‘lsa ham real kataklar farqli bo‘lib, anti-dependency execution tartibini cheklamaydi.
Bog‘liq tushunchalar
anti-dependency, register renaming, physical register, alias analysis, out-of-order execution, register allocation