280 likes | 419 Views
תורת הקומפילציה תרגול 13: Data Flow Analysis. נכתב ע"י אלכס קוגן ( ( sakogan@cs סמסטר חורף, תשס"ח עודכן: סמסטר אביב 2012. מוטיבציה. על מנת לבצע אופטימיזציות רבות, נדרש חישוב גלובלי כדי לזהות את כל הפקודות / משתנים / ביטויים אשר מקיימים תכונה מסוימת בנקודה מסוימת בתכנית. לדוגמא:
E N D
תורת הקומפילציהתרגול 13:Data Flow Analysis נכתב ע"י אלכס קוגן ((sakogan@cs סמסטר חורף, תשס"ח עודכן: סמסטר אביב 2012
מוטיבציה • על מנת לבצע אופטימיזציות רבות, נדרש חישוב גלובלי כדי לזהות את כל הפקודות / משתנים / ביטויים אשר מקיימים תכונה מסוימת בנקודה מסוימת בתכנית. • לדוגמא: • ניתוח חיוּת – לטובת Dead Code Elimination. • ניתוח aliasing – לטובת Copy Propagation.
in B out בעיות DFA • קלט: CFG, כאשר • כל צומת הוא בלוק בסיסי, או • כל צומת הוא פקודה יחידה • הופך את הניתוח ברמה של צומת לפשוט יותר • מגדיל סיבוכיות זמן ומקום • פלט: קבוצות in(B)ו- out(B) לכל צומת B ב-CFG • in(B) - מתייחסת לנק' שלפני הפקודה הראשונה ב-B • out(B) - מתייחסת לנק' שאחרי הפקודה האחרונה ב-B • מה מכילות הקבוצות? • תלוי בבעיה - משתנים / השמות / ביטויים וכו' • הערה: בד"כ לאופטימיזציה עצמה נצטרך רק אחת משתי הקבוצות, אבל בשביל החישוב צריך את שתיהן
בעיות DFA - המשך • ההשפעה של B על in/out מסומנת ע"י fB • יכול להוסיף פריטי מידע חדשים לאלה שנכנסו אליו ("ליצור") • יכול להסיר פריטי מידע מאלה שנכנסו אליו ("להרוג") • ל-fB שני מרכיבים: • gen(B) - דברים שנוצרים ב-B • kill(B) - דברים ש-B הורג fB = gen(B) [ X \ kill(B) ] • כאשר X מסמן קבוצת איברים שנכנסים ל-B • X = in(B) או X = out(B) • תלוי בכיוון זרימת המידע בבעיה
בעיות DFA - המשך • צורת החישוב - אחת מהשתיים: • סריקה קדמית - המידע "זורם" קדימה • למשל, בחישוב של reaching definitions • סריקה אחורית - המידע "זורם" אחורה • למשל, בניתוח חיות
out(B) = fB (in(B)) in(B) = out(S) (S,B) CFG או ∩ משוואות זרימה - סריקה קדמית • מה שיוצא מ-B מתקבל מהפעלת fB על מה שנכנס אליו • מה שנכנס ל-B מתקבל מהאבות של B בגרף CFG • בהמשך נראה איך (חיתוך או איחוד)
in(B) = fB (out(B)) out(B) = in(D) (B,D) CFG או ∩ משוואות זרימה - סריקה אחורית • בדיוק כמו בסריקה קדמית, רק ש-in ו-out מתחלפים • הפעם, מסתכלים על הבנים של B ב-CFG
משוואות זרימה • אז איך קובעים יחס בין in(B) לבין קבוצות out(S) עבור אבות של B ב-CFG בסריקה קדמית? • כנ"ל בסריקה אחורית • איחוד או חיתוך? • בעיות must - מנוסחות עם דרישה שצריכה להתקיים על כל המסלולים ב-CFG • למשל, copy propagation (נראה בהמשך) • נשתמש בחיתוך • בעיות may - מנוסחות עם דרישה שצריכה להתקיים על מסלול כלשהו ב-CFG • למשל, ניתוח חיות ו-reaching definitions • נשתמש באיחוד
חישוב משוואות הזרימה • המשוואות עשיות ליצור תלויות מעגליות • למשל, במקרה של לולאה • ראינו מקרים כאלה בעבר (first, follow) • החישוב יתבצע בצורה איטרטיבית
חישוב משוואות הזרימה - המשך • מאתחלים את in(B) או out(B) בצורה שמרנית • בעיות may (איחוד) - לפי מה שמובטח שצריך להיות בפנים • מה שנכנס באתחול עלול להישאר בתוצאה סופית • אומדן שמרני - קבוצה ריקה (כי רק מוסיפים דברים) • בעיות must (חיתוך) - לפי מה שמובטח שלא יהיה בפנים • מה שלא נכנס באתחול עלול לא להופיע בתוצאה סופית • אומדן שמרני - כל פריטי מידע בתכנית (כי רק מורידים דברים) • לעתים הבלוק הראשון או האחרון בתכנית צריכים טיפול מיוחד • כל עוד יש שינויים, מחשבים in ו-out מחדש לכל הבלוקים בתכנית לפי משוואות הזרימה • לפי סדר כלשהו
סיווג בעיות DFA • הצירוף של שני הפרמטרים האלה קובע את צורת משאוות הזרימה • החלק המכריע בפתרון בעיית DFA הינו סיווג נכון של הבעיה
דוגמה - Copy Propagation • הרעיון: אחרי העתקה x:=y, נחליף את x ב-y במקומות בהם משתמשים ב-x • דוגמה: a := b a := b c := a + d c := b + d e := c * a e := c * b • מה הרווחנו? • אם x לא יהיה חי אחרי הפקודה x:=y, נוכל למחוק את הפקודה
B0: בלוק ראשון ב-CFG S: x:=y y:= … x:= … p: שימוש ב-x Copy Propagation- המשך • נניח כי כל צומת ב-CFG מכיל פקודה יחידה • מתי אסור לבצע את ההחלפה? • יש הגדרה של x שאינה s שמגיעה ל-p • יש מסלול בין s ל-p שעליו y מוגדר מחדש • יש מסלול מהצומת התחילי ל-p שאינו עובר ב-s
Copy Propagation- המשך • מהי מטרת החישוב? • כל פקודות ההעתקה x:=y כך שאם רואים בנקודה בתכנית שימוש ב-x, מותר להחליף אותו ב-y • מהם פריטי מידע בקבוצות in/out? • פקודות ההעתקה שמופיעות בתכנית • מהו כיוון זרימת המידע? (קדמית / אחורית) • קדמית, כי כל העתקה "משפיעה קדימה" • אחרי העתקה x:=y מותר להחליף את x ב-y
Copy Propagation- המשך • מהו gen(B)? • פקודות העתקה x:=y אם מופיעה ב-B • מייד אחרי הפקודה x:=y מותר להחליף את x ב-y • מהו kill(B)? • העתקות x:=y כך ש: • B מכיל כתיבה (אחרת) ל-x (מקרה 1) • B מכיל כתיבה ל-y (מקרה 2) • נטפל במקרה 3 בנפרד
Copy Propagation- המשך • מהו סוג הבעיה? (may / must) • בעיית must, כי מספיק שיהיה מסלול אחד "רע" כדי שלא נוכל לבצע החלפה • כל המסלולים צריכים לקיים את הדרישות • משוואות הזרימה: • בעיית must, זרימה קדמית out(B) = fB (in(B)) in(B) = ∩ out(S) (S,B) CFG
Copy Propagation- המשך • איך נאתחל את הקבוצות? • בצורה שמרנית המתאימה לבעיית must • לכל בלוק פרט ל-B0: • עבור B0: • מספיק לאתחל רק אחת מבין הקבוצות in ו-out in(B) = out(B) = כל ההעתקות בתכנית in(B) = Ø out(B0) = gen(B0) ( = fB0(Ø) )
Copy Propagation- המשך • מדוע יש טיפול מיוחד בבלוק הראשון? • בגלל מקרה 3! • צריך לוודא שאם מחליפים x ב-y, ההעתקה x:=y נמצאת על כל מסלול מ-Bo • ל-Bo אין אבות ב-CFG • כל דבר שנכניס ל-in/out(B) באיתחול, ישאר שם עד הסוף ויחלחל לבנים • לא נצליח לזהות העתקות שאינן נמצאות על מסלול מ-B0 • ההעתקה היחידה שנמצאת על כל מסלול מ-B0 לנק' out(B0) היא ההעתקה המופיעה ב-B0 (אם יש כזו)
שאלה ממבחן • משתנה x הוא חיוני בנקודה p אם בכל מסלול חישוב מ-p מתבצעת הדפסה לפלט של x לפני שמתבצעת אליו כתיבה. • לדוגמא: y=3; x=6; print x; y=5; print y; x חיוני, y אינו חיוני y חיוני
שאלה ממבחן א. מהם הקבוצות in/out? • יגדירו את קבוצת המשתנים החיוניים בכניסה/יציאה מהבלוק. • פריטי המידע: כל המשתנים בתכנית. ב. כיוון זרימת המידע: • אחורית: בכל נקודה, הדפסת המשתנה תהפוך אותו לחיוני, והשמה למשתנה תבטל את היותו חיוני. ג. מהו סוג הבעיה? (may / must) • בעיית must, כי נדרש שבכל אחד מהמסלולים תהיה הדפסה לפני השמה. out(B) = ∩ in(D) (B,D) CFG
שאלה ממבחן ד. מהו gen(B)? • כל המשתנים שמודפסים ב-B • וגם אין לתוכם השמה, או שכל ההשמות לתוכם מופיעות לאחר פקודת הדפסה שלהם. מהו kill(B)? • כל המשתנים שנכתב אליהם ערך ב-B. • האם צריך "וגם אין הדפסה שלהם לפני הכתיבה"? • לא חייבים, כי ממילא משתנים אלה יופיעו ב-gen(B) ולכן גם ב-fB .
שאלה ממבחן • משוואות הזרימה: ה. איך נאתחל את הקבוצות? • אתחול שמרני עבור בעיית must: • נניח צומת סיום יחיד, Bfin לו אין קשתות יוצאות: • לכל בלוק Bב CFG שאינו Bfin: in(B) = fB (out(B)) = gen(B) [ out(B) \ kill(B) ] out(B) = ∩in(D) (B,D) CFG out(Bfin) = Ø, in(Bfin) = gen(Bfin ) סימון לכל המשתנים בתוכנית in(B) = U , out(B) = U
ניתוח 2-חיוּת • תזכורת: משתנה x הוא חי בנקודה p בתכנית אם קיים מסלול מ-p בו יש שימוש ב-x (קריאת ערך x) לפני הגדרה מחודשת (כתיבה מחדש ל-x). • נגדיר: משתנה x הוא 2-חי בנקודה p בתכנית אם קיים מסלול מ-p בו יש שני שימושים ב-x לפחות לפני הגדרה מחודשת. א. in2(B),out2(B) – קבוצת המשתנים ה-2 חיים בכניסה/יציאה מהבלוק. ב. זרימה אחורית – בדומה לניתוח חיוּת. ג. בעיית may – מספיק מסלול אחד שיקיים את התכונה.
ניתוח 2-חיוּת - המשך • אילו משתנים נרצה שיופיעו ב in2(B)? • כל משתנה ב- out2 (B) עבורו אין הגדרה מחודשת ב-B. • כל משתנה עם לפחות שני שימושים ב-B לפני הגדרה מחודשת. • כל משתנה שיש לו שימוש ב-B, הוא חי ביציאה מ-B ולא הוגדר מחדש ב-B. ד. מהו gen(B)? • כדי למצוא את המשתנים החיים ביציאה מ-B נבצע הרצה מקדימה של ניתוח חיוּת. מהו kill(B)? • כל המשתנים שנכתב אליהם ערך ב-B.
ניתוח 2-חיוּת - המשך kill(B) = { x | B משתנה שהוגדר מחדש ב- x{ gen1(B) = { x | שני שימושים בבלוק לפני הגדרה מחודשת x {ל gen2(B) = { x | יש שימוש בבלוק ואין הגדרה מחודשת x {ל ה. אתחול הקבוצות: in2(B) = gen2 (B) [out2(B)\kill(B)]= ( gen1(B) [gen2(B)∩out1(B)] ) [out2(B)\kill(B)] out2(B) = in2(D) (B,D) CFG הקבוצה out שהתקבלה מההרצה המוקדמת של ניתוח החיוּת B, in2(B) = out2(B) = Ø
ניתוח k-חיוּת • בצורה דומה ב ink(B) יופיעו המשתנים הבאים: 1. כל משתנה ב- outk(B) עבורו אין הגדרה מחודשת ב-B. 2. כל משתנה ב-outk-1(B) עם לפחות שימוש אחד ב-B ואשר עבורו אין הגדרה מחודשת ב-B. ... • כל משתנה ב-out1(B) עם לפחות k-1 שימושים ב-B ואשר עבורו אין הגדרה מחודשת ב-B. k+1. כל משתנה עם k שימושים ב-B לפני הגדרה מחודשת. • מדוע האנליזה שימושית? • ככל שיש יותר שימושים למשתנה, תגדל המוטיבציה לשמור אותו ברג'יסטר ולא בזיכרון.
סיכום • מה משתנה בעקבות ההנחה על ייצוג צמתים ב-CFG (בלוק בסיסי / פקודה בודדת)? • משואות הזרימה • אתחול הקבוצות in / out • פונקציות gen ו-kill • הצורה בה פתרנו את השאלות לפי סדר השאלות ששאלנו הינה מתכון לפתרון כל שאלות ה-DFA