43
1 הההה הההההההההה236360 ההההה11 ההההה ההההCode Generation Aho, Lam, Sethi and Ullman – Chapter 8

1 תורת הקומפילציה 236360 הרצאה 11 יצירת הקוד Code Generation Aho, Lam, Sethi and Ullman – Chapter 8

  • View
    233

  • Download
    8

Embed Size (px)

Citation preview

Page 1: 1 תורת הקומפילציה 236360 הרצאה 11 יצירת הקוד Code Generation Aho, Lam, Sethi and Ullman – Chapter 8

1

236360תורת הקומפילציה 11 הרצאה

יצירת הקוד Code Generation

Aho, Lam, Sethi and Ullman – Chapter 8

Page 2: 1 תורת הקומפילציה 236360 הרצאה 11 יצירת הקוד Code Generation Aho, Lam, Sethi and Ullman – Chapter 8

2 2

יצירת קוד

syntax analysis

semantic analysis

code generation

syntax tree

intermediate code

: מייצרים קוד עבור מכונה ספציפית.back-endהגענו ל-

הדיון מתאים לקוד שעבר אופטימיזציה או קוד לפני אופטימיזציה.

ההנחה היא שקוד הביניים לא מכיל שגיאות )בשלב זה לא נהוג לחפש שגיאות(.

Page 3: 1 תורת הקומפילציה 236360 הרצאה 11 יצירת הקוד Code Generation Aho, Lam, Sethi and Ullman – Chapter 8

3 3

מטרות

יצירת קוד בעל איכות טובהיעילות בזמן ריצהיעילות במקום הנדרש בזמן ריצהלאחרונה - יעילות בצריכת אנרגיהגודל קוד קטן ככל האפשר ניצול יעיל של משאבי המכונה )למשל, ניצול טוב של הרגיסטרים, או

ניצול פקודות מכונה מהירות ייחודיות(

יצירת קוד בזמן סביר.מותר לקומפיילר לרוץ לאט כדי ליצור תכנית שרצה מהר

.אבל בגבולות הטעם הטוב יצירת קוד אופטימלי היאNP-hard לכן משתמשים באלגוריתמים ,

היוריסטיים.

Page 4: 1 תורת הקומפילציה 236360 הרצאה 11 יצירת הקוד Code Generation Aho, Lam, Sethi and Ullman – Chapter 8

4 4

code generatorהקלט והפלט של ה-

קוד בשפת הביניים + מידע מטבלת הסמלים )וכל מידע אחר קלט:(. front-endשנרצה להעביר מה-

פלט: שפת המטרהabsolute machine code מוכן להרצה מיידית )מכיל כתובות :

אבסולוטיות(. תוכניותcom-ב DOSלא ממש קיים בארכיטקטורות מודרניות

relocatable code .כתובות יחסיות, מאפשר קומפילציה נפרדת : דורשlink-load.לפני הביצוע קבציobj קבצי( tpu)'וכו ,

assembly language : דורש ביצעassembly.לפני הריצה .יצירת קוד יותר קצר, מאפשר שימוש במקרו, פקודות סימבוליות

Page 5: 1 תורת הקומפילציה 236360 הרצאה 11 יצירת הקוד Code Generation Aho, Lam, Sethi and Ullman – Chapter 8

5 5

אתגריםניהול זיכרון - היכן נמצא משתנה במהלך הביצוע?

הבנת פקודות מכונה:.אוסף רחב מצריך החלטה נבונה יותר באיזו אופציה עדיף להשתמש...'מה העלות בזיכרון של כל פקודה? צריכת אנרגיה, יעילות וכו

הקצאת רגיסטרים

caching וב- pipeliningבחירת סדר החישוב תוך התחשבות ב-

אנו נדבר על: עלות פקודות)יצירת קוד לקפיצה לרוטינה )וחזרה ,בלוקים בסיסייםControl Flow Graph.ואופטימיזציות בסיסיות ,.ייצור קוד תוך כדי מעקב על מיקום המשתנים בזיכרון וברגיסטרים .הקצאת רגיסטרים

Page 6: 1 תורת הקומפילציה 236360 הרצאה 11 יצירת הקוד Code Generation Aho, Lam, Sethi and Ullman – Chapter 8

6 6

מכונת מטרה לדוגמא

byte addressability, 4-byte words ,

n – רגיסטרים R0, . . . Rn-1

OP source, destinationמבנה הפקודות

צורת האופרנדים

address form mode

M M absolute

R R register

c + content ( R ) c ( R ) indexed

content ( R ) * R indirect register

content ( c + content ( R ) ) * c ( R ) indirect indexed

c (constant – not an address) # c literal

Page 7: 1 תורת הקומפילציה 236360 הרצאה 11 יצירת הקוד Code Generation Aho, Lam, Sethi and Ullman – Chapter 8

7

אורך הקוד שנוצר

מילים.1-3כל פקודה תופסת בין

אנו נניח שבמילה אחת אפשר להכניס:Op-code ,שני מספרים של רגיסטרים, צורת האופרנד )מיעון עקיף ,

ישיר, אינדקס וכיו"ב(.

אבל לכל כתובת בזיכרון או קבוע יש להוסיף מילה )ראה עמודה ימנית(.

Length cost address form mode

1 M M absolute

0 R R register

1 c + content ( R ) c ( R ) indexed

0 content ( R ) * R indirect register

1 content ( c + content ( R ) ) * c ( R ) indirect indexed

1 c (constant – not an address) # c literal

Op-code + info

More for op 1 ?

More for op 2 ?

Page 8: 1 תורת הקומפילציה 236360 הרצאה 11 יצירת הקוד Code Generation Aho, Lam, Sethi and Ullman – Chapter 8

8 8

דוגמאות

MOV R0,123

בזכרון.123 לכתובת 0העתק את הערך של רגיסטר .2אורך פקודה =

ADD 4)R0(,123

.123{, לכתובת 0 ועוד ערך רגיסטר 4הוסף את הערך שבכתובת הזכרון }.3 אורך פקודה =

SUB *4)R0(,R1

.R1, מ-R0+4החסר את הערך שבתא הזכרון, שכתובתו נמצאת בכתובת )R1:= R1 - *)4+R0(( = 2 אורך פקודה.

MOV #1,R0

.R0" ל-1כתוב את הערך ".2 אורך פקודה =

Page 9: 1 תורת הקומפילציה 236360 הרצאה 11 יצירת הקוד Code Generation Aho, Lam, Sethi and Ullman – Chapter 8

9

ניהול הזיכרון

אזור סטטי בזיכרון שמכיל קוד

אזור סטטי שמכיל משתנים סטטיים )גלובליים(

: אזור שמנוהל דינאמית עבור אובייקטים שהתוכנית מקצה.heapה-

שבו מנוהלים רשומות ההפעלה של הרוטינות.stackה-

Page 10: 1 תורת הקומפילציה 236360 הרצאה 11 יצירת הקוד Code Generation Aho, Lam, Sethi and Ullman – Chapter 8

10

ניהול רשומות ההפעלה לפרוצדורות

סטטי ודינאמי. scopingנפריד בין

דינאמי מנהלים מחסנית עבור כל שם משתנה. scopeכזכור עבור

מייצרים כניסה חדשה במחסנית בכל פעם שנכנסים לבלוק שבו מוגדר המשתנה,

בכל פעם שיוצאים מבלוק כזה )לכל משתנה המוגדר בו(.popעושים

היתרון: אין צורך במחסנית של רשומות הפעלה, ולכל פרוצדורה יש רשומת הפעלה יחידה.

המידע בטבלת הסמלים מפנה למחסנית של כל משתנה.

את כתובות החזרה שומרים במחסנית ומעדכנים בכל כניסה ויציאה מרוטינה.

סטטי. לא נדבר על ניהול המחסניות, אלא על איך scopingנעבור ל-נראית קריאה לרוטינה, חזרה מרוטינה, ורשומת ההפעלה.

Page 11: 1 תורת הקומפילציה 236360 הרצאה 11 יצירת הקוד Code Generation Aho, Lam, Sethi and Ullman – Chapter 8

11

Static scopingכאן המשתנים יושבים בתוך רשומת ההפעלה.

.stack pointerהכתובות הן יחסיות ל-

ראשית, נתייחס לקפיצה לרוטינה ולצעדים המתבצעים בקפיצה ובחזרה.

יצביע על ההתחלה של רשומת ההפעלה האחרונה SPבדוגמא שלנו ה-, ולכן stackב--הoffset.ים יהיו חיוביים--כשנקפוץ לרוטינה, נקדם את הSP בגודל הרשומה של הרוטינה

הקוראת.

רשומת הפעלה קודמת

רשומת הפעלה נוכחית

SPכתובות עולות

Page 12: 1 תורת הקומפילציה 236360 הרצאה 11 יצירת הקוד Code Generation Aho, Lam, Sethi and Ullman – Chapter 8

12 12

scopingניהול מחסנית רשומות הפעלה ב-סטטי

main

MOV #stackstart , SP

… code for the main procedure …

HALT

calling a procedure

ADD #caller.recordsize , SP

MOV #here + 16 , *SP

GOTO callee.code_areaSUB #caller.recordsize , SP

return from a procedure

GOTO *0 ( SP )

רגיסטר מיוחד, מצביע לראש המחסנית. יצביע לראש רשומת ההפעלה הנוכחית.

נניח לשם פשטות שכתובת החזרה נמצאת

בתחילת רשומת ההפעלה.

Page 13: 1 תורת הקומפילציה 236360 הרצאה 11 יצירת הקוד Code Generation Aho, Lam, Sethi and Ullman – Chapter 8

13 13

ניהול מחסנית – דוגמא

/* code for main */action1

call qaction2

halt

/* code for p */action3

return

/* code for q */action4

call paction5

call qaction6

call qreturn

Page 14: 1 תורת הקומפילציה 236360 הרצאה 11 יצירת הקוד Code Generation Aho, Lam, Sethi and Ullman – Chapter 8

14 14

code for q code for mainACTION4 300: initialize the stack MOVE #600,SP 100:ADD #qsize,SP 320: ACTION1 108:

push return address MOV #344,*SP 328: call sequence begins ADD #main_size,SP 128:

call p GOTO 200 336: push return address MOV #152,*SP 136:SUB #qsize,SP 344: call q GOTO 300 144:ACTION5 352: restore SP SUB #ssize,SP 152:ADD #qsize,SP 372: ACTION2 160:

push return address MOV #396,*SP 380: HALT 180:call q GOTO 300 388: . . .

SUB #qsize,SP 396: code for pACTION6 404: ACTION3 200:ADD #qsize,SP 424: return GOTO *0(SP) 220:

push return address MOV #448,*SP 432: . . .call q GOTO 300 440:

SUB #qsize,SP 448:return GOTO *0(SP) 456:

. . .stack starts here 600:

ניהול מחסנית – דוגמא

Page 15: 1 תורת הקומפילציה 236360 הרצאה 11 יצירת הקוד Code Generation Aho, Lam, Sethi and Ullman – Chapter 8

15 15

המקור תוכנית היא שורה בx := 0דוגמא – נניח ש-

משתנים סטטיים -נניח שx( ( אמור להמצא בהיסט offset12 בקוד ביניים נראהstatic [12] := 0 נקבל:100בקוד המכונה, אם האזור הסטטי מתחיל בכתובת ,

MOV #0, 112קוד מכונה –

הקצאה של משתנים מקומיים במחסנית -נניח שx משתנה מקומי הממוקם ברשומת ההפעלה המוצבעת ע"י

SP

t1 := 12 + SP

* t1 := 0

– בפקודות מכונה MOV #0, 12 ) SP (

קוד ביניים )רביעות(

scopingחישוב כתובות עבור משתנים )ב-סטטי(

Page 16: 1 תורת הקומפילציה 236360 הרצאה 11 יצירת הקוד Code Generation Aho, Lam, Sethi and Ullman – Chapter 8

16

מבנה התוכנית המיוצרת

הבנת ההקשר של הפקודה יכולה להואיל לייצור הקוד)בפרט הקצאת רגיסטרים ובחירת הפקודות שבהן נשתמש(.

- . Basic blockמושג מאד חשוב בהבנת קוד הוא בלוק בסיסי

הוא סדרת פקודות עם בלוק בסיסי כניסה יחידה )לפקודה הראשונה( – אין קפיצה בקוד הקופצת לאמצע

בלוק. יציאה יחידה )מהפקודה האחרונה( – הקוד יתבצע ללא שום קפיצות

עד הגעתו לפקודה האחרונה בבלוק, שעשויה להיות קפיצה או קפיצה מותנית, או פקודה שמהווה יעד של קפיצה ממקור אחר, או סיום

התוכנית.

הרעיון הוא שכאשר נכנסים לבלוק, עושים זאת מהפקודה הראשונה ואז עוברים את הפקודות בבלוק אחת אחת בלי לצאת.

נגדיר קשת בין שני בלוקים אם הפקודה האחרונה של בלוק המקור עשויה לקפוץ אל הפקודה הראשונה של בלוק היעד.

Page 17: 1 תורת הקומפילציה 236360 הרצאה 11 יצירת הקוד Code Generation Aho, Lam, Sethi and Ullman – Chapter 8

17

Basic Blocks Example

t1 := 4 * i

t2 := a [ t1 ]

if t2 <= 20 goto B3

t3 := 4 * i

t4 := b [ t3 ]

goto B4

t5 := t2 * t4

t6 := prod + t5

prod := t6

goto B4

False

t7 := i + 1

i := t2

Goto B5

B1

B2 B3

B4

True

Page 18: 1 תורת הקומפילציה 236360 הרצאה 11 יצירת הקוד Code Generation Aho, Lam, Sethi and Ullman – Chapter 8

18 18

פירוק תוכנית לבלוקים בסיסיים

Input: A sequence of three-address statements

Output: A list of basic blocks with each three-address statement in exactly one block

Method We first determine the set of leaders )the first statements of

basic blocks(. The first statement is a leader Any statement that is the target of a conditional or

unconditional jump is a leader Any statement that immediately follows a goto or

conditional jump statement is a leader For each leader, its basic block consists of the leader and all

statements up to but not including the next leader or the end of the program

Page 19: 1 תורת הקומפילציה 236360 הרצאה 11 יצירת הקוד Code Generation Aho, Lam, Sethi and Ullman – Chapter 8

19 19

(Control )Flow Graph

– הבלוקים הבסיסייםצמתי הגרף

– קשת מקשרת שני בלוקים קשתות הגרףאם קיימת הפנית בקרה מהראשון לשני )או

פשוט המשך ישיר של זרימת הבקרה(

– קבוצה קשירה היטב של בלוקים לולאהבעלת כניסה יחידה

– לולאה ללא תת-לולאותלולאה פנימית

הערה – נהוג להשתמש בשמות הבלוקים הבסיסיים כמטרת הקפיצה )ולא במספרים

סידוריים של הרביעיות המתאימות( על מנת להקל הזזות של הבלוקים בסיסיים

B1

prod := 0i := 1

B2

t1 := 4 * i

t2 := a [ t1 ]

t3 := 4 * i

t4 := b [ t3 ]

t5 := t2 * t4

t6 := prod + t5

prod := t6

t7 := i + 1

i := t7

if i <= 20 goto B2

Page 20: 1 תורת הקומפילציה 236360 הרצאה 11 יצירת הקוד Code Generation Aho, Lam, Sethi and Ullman – Chapter 8

20

דוגמא מהספר לקוד, וגרף זרימת בקרה מתאים

Page 21: 1 תורת הקומפילציה 236360 הרצאה 11 יצירת הקוד Code Generation Aho, Lam, Sethi and Ullman – Chapter 8

21

אופטימיזציות

בתוך אפשר לקבל שיפורים משמעותיים בזמן בקוד גם כשמתבוננים רק . כלומר:בלוקים בסיסיים

מנתחים את המידע הנמצא בתוך הבלוק ולא מתחשבים במה שקורהמחוץ לבלוק

עושים שינויים לוקליים בלבד

.בכל הבלוקים שבתוך פרוצדורהרמת דיוק גבוהה יותר משתמשת ,אם יש פיצול בזרימת הבקרה, לא יודעים מה קורה בחישוב בפועל

וצריך לעבוד באופן שמרני או ליברלי, כתלות במטרת האופטימיזציה..שיטות אלו יותר מסובכות ונדבר עליהן בהמשך הקורס

אבל:בכל הבלוקים שבתוכנית ניתן לדייק עוד יותר אם מתחשבים ,לא תמיד כל הבלוקים ידועים )קישור לספריות לאחר הקימפול

וכיו"ב(

21

Page 22: 1 תורת הקומפילציה 236360 הרצאה 11 יצירת הקוד Code Generation Aho, Lam, Sethi and Ullman – Chapter 8

22 22

2תהגדרה, שימוש, ו של משתניםח3יו

הקצאת משתנים נכונה לרגיסטרים היא קריטית ליעילות הריצה.הידיעה מתי ערכים בתוכנית רלוונטיים או "חיים" היא קריטית להקצאה

יעילה של רגיסטרים.z ו- y- ב משתמשו x את מגדיר x := y + zמשפט מהסוג

בנקודה נתונה אם נעשה שימוש בערך שלו לאחר הנקודה חימשתנה הוא האמורה.

, ויש מסלול x משתמשת ב-j, ופקודה i מוגדר בפקודה xאם משתנה משתמשת בערך j(, אז נאמר שפקודה x )שאינו משנה את j ל-iחישוב מ-

.i שהוגדר בפקודה xשל ,בפרטx חי בפקודה i ובכל המסלול בין i-ל j.

נחשב שימוש של משתנים במקרה הפשוט שהכול קורה בתוך בלוק בסיסי.

: בשיעור Data Flow Analysis)עבודה עם כמה בלוקים תשתמש ב-הבא(.

Page 23: 1 תורת הקומפילציה 236360 הרצאה 11 יצירת הקוד Code Generation Aho, Lam, Sethi and Ullman – Chapter 8

23 23

next-useטבלת ה-

עבור כל שורה בבלוק נתון, נרצה לשמור )עבור כל משתנה אליו מתייחסת שורה זו(:

האם המשתנה חי )כלומר יש בו שימוש בעתיד(, ואם הוא חי.באיזו פקודה יקרה השימוש הבא במשתנה

החישוב נעשה על-ידי סריקה של הבלוק מסופו לעבר תחילתו

הנחות שמרניות: כל המשתנים שאינם מקומיים בבלוק, חיים בסוף הבלוק )כלומר, נעשה בהם שימוש בהמשך(.

-שימו לב שיש הרבה משתנים זמניים לוקליים בintermediate code ,ולכן אפילו טיפול לוקלי הוא רלוונטי.

נניח שהמידע מי לוקלי לבלוק מושג באיזושהי צורה יעילה. )קל לבדוקאת זה במעבר על התוכנית.(

Page 24: 1 תורת הקומפילציה 236360 הרצאה 11 יצירת הקוד Code Generation Aho, Lam, Sethi and Ullman – Chapter 8

24 24

next useחישוב ה-

– ברמת הבלוק הבודד – מהסוף להתחלה. next-useחישוב ה-

נעזר בטבלת הסמלים לשמור מידע על המשתנים.

:iנניח שבטיפול מהסוף להתחלה הגענו לפקודה

i: x := y op z

עד z ו- y, x את האינפורמציה שנאספה בטבלת הסמלים על iנצמיד ל- 1.עתה.

נקבע בטבלת הסמלים )עבור הפקודות המוקדמות יותר בבלוק(:2.

x"לא חי"; "אין שימוש בהמשך" –

נקבע בטבלת הסמלים:3.

y, z -חיים"; "השימוש הבא – ב" – i"

– חשוב3 ו- 2הערה – הסדר בין כיx עשוי להיות y.

213. x := 1214. y := x + 3215. z := x * 3216. x := y * z

Page 25: 1 תורת הקומפילציה 236360 הרצאה 11 יצירת הקוד Code Generation Aho, Lam, Sethi and Ullman – Chapter 8

25 25

בתוך בלוקים טרנספורמציות פשוטות )וחשובות(בסיסיים

סילוק ביטויים משותפים

ביטול "קוד מת"השמה למשתנה שלא חי לאחר מכן

החלפת סדר בין פקודות שאינן תלויות אחת בשנייה)לקיצור הזמן בו משתנה חי )כלומר הזמן שהוא דורש רגיסטר לייעולpipeline.או מקבול פנימי

:= b + c a:= a – d b:= b + c c:= a – d dd := b

Page 26: 1 תורת הקומפילציה 236360 הרצאה 11 יצירת הקוד Code Generation Aho, Lam, Sethi and Ullman – Chapter 8

26 26

בתוך בלוקים טרנספורמציות פשוטות )וחשובות(בסיסיים

פישוטים אלגבריים::שוויונות

x + 0 = 0 + x = x – 0 = x

x * 1 = 1 * x = x / 1 = x :שימוש בפקודות זולות יותר

x ^ 2 = x * x

2i * x = shift-left)x,i(

2 * x = x + x

x / 2i = shift-right)x,i(...וכולי

Page 27: 1 תורת הקומפילציה 236360 הרצאה 11 יצירת הקוד Code Generation Aho, Lam, Sethi and Ullman – Chapter 8

27 27

תהליך פשוט ליצירת קוד

נייצר את הקוד פקודה פקודה, נטפל בכל בלוק בנפרד.

לכל פקודה נבדוק היכן נמצאים האופרנדים

, שבו הפקודות עובדות על רגיסטרים, RISCנניח, למען הפשטות מחשב . load ו-storeפרט ל-

Page 28: 1 תורת הקומפילציה 236360 הרצאה 11 יצירת הקוד Code Generation Aho, Lam, Sethi and Ullman – Chapter 8

28 28

מעקב אחרי משתנים ורגיסטרים (Descriptors)

-stackנתעלם כרגע מרגיסטרים שאנו עושים בהם שימוש גלובלי כמו pointer .וכיו"ב ונניח שישנם רגיסטרים לשימושינו בבלוק

מה יש בו descriptorלכל רגיסטר – נרשום ב-בתחילת כל בלוק כל הרגיסטרים ריקיםבמהלך ייצור הקוד, כל רגיסטר יכיל משתנה אחד או יותר פקודה העתקה מהסוגx := y תגרום לרגיסטר להחזיק ערך של יותר

ממשתנה אחד.

המחזיק את הכתובת address descriptorלכל משתנה של התוכנית יש )או הכתובות( בו הוא נמצא.

-רגיסטר, כתובת בזיכרון, מיקום בstack.-בד"כ הdescriptor.נשמר בטבלת הסמלים

Page 29: 1 תורת הקומפילציה 236360 הרצאה 11 יצירת הקוד Code Generation Aho, Lam, Sethi and Ullman – Chapter 8

29 29

code generationאלגוריתם ל- מבלוק בסיסי מסוים.three-addressקלט: רצף של פקודות

For each three-address statement x := y op z, perform the following:

1. Invoke getreg )x := y op z( to determine locations Rx, Ry, and Rz.

2. If Ry does not contain y, issue: “LD Ry, y’ ”, for a location y’ of y.

3. If Rz does not contain z, issue: “LD Rz, z’ ”, for a location z’ of z.

4. Issue the instruction “OP Rx,Ry,Rz”

5. Update the address descriptors of x, y, z, if necessary. In particular,

Rx is the only location of x now, and Rx contains only x )remove Rx from other address descriptors(.

Page 30: 1 תורת הקומפילציה 236360 הרצאה 11 יצירת הקוד Code Generation Aho, Lam, Sethi and Ullman – Chapter 8

30 30

יצירת קוד – פעולות אחרות

הטיפול בפעולות אונריות – דומה

x := yמצריך עדכון המתארים

עם סיום העבודה ברמת הבלוק הבסיסי שומרים את ערכי המשתנים שלא נמצאים במקומם הטבעי )למשל נמצאים רק בתוך רגיסטרים(.

אלא אם יש לנו אינפורמציה מקיפה יותר של live-dead.בין בלוקים

Page 31: 1 תורת הקומפילציה 236360 הרצאה 11 יצירת הקוד Code Generation Aho, Lam, Sethi and Ullman – Chapter 8

31 31

(getregהקצאת רגיסטרים )הפונקציה

x := y op zקלט:

. z, ו-x, yהמטרה – הקצאת רגיסטר ל- שקולה.z, בחירת עבור yנתחיל ב-

.Ry=R, קבע R ברגיסטר yאם 1.

. Ry=R, קבע Rאחרת, אם יש רגיסטר פנוי 2.

z אינו אופרנד )x, וגם xאחרת, אם יש רגיסטר המכיל רק את 3..Ry=Rבמקרה זה( אז קבע

. Ry=R אינו חי, קבע v שהמשתנה שבו Rאחרת, אם יש רגיסטר 4.

קיים גם במקום אחר, v שהמשתנה שבו Rאחרת אם יש רגיסטר 5.. Ry=Rקבע

כלשהו שמייצג מספר מינימלי של משתנים Rאחרת, בחר רגיסטר 6.{v1, v2, …, vm לכל משתנה שמיוצג רק ע"י .}R העתק את ערכו

. Ry=Rלזיכרון. קבע

אם רלוונטי( vi, )או R, v של descriptorבכל מקרה עדכן את ה-7.בהתאם.

Page 32: 1 תורת הקומפילציה 236360 הרצאה 11 יצירת הקוד Code Generation Aho, Lam, Sethi and Ullman – Chapter 8

32 32

x הקצאת רגיסטר ל-חלק שני:

x := y op zקלט:

y)זה בסדר גם אם . Rx=R, קבע xאת רק המכיל R ברגיסטר xאם 1.(.x זהים ל-zאו

( לאחר הפקודה הנוכחית, z )או ב-yאחרת, אם לא משתמשים ב-2.והרגיסטר שנקבע לו מייצג אותו באופן יחיד, אז ניתן לקבוע את

(. z )או y להיות זהה לרגיסטר של xהרגיסטר של ההמשך מאד דומה

...Rאחרת, אם יש רגיסטר פנוי 3.

אינו חי... v שהמשתנה שבו Rאחרת, אם יש רגיסטר 4.

כלשהו שמייצג מספר מינימאלי של משתנים Rאחרת, בחר רגיסטר 5.{v1, v2, …, vm לכל משתנה העתק את ערכו לזיכרון, וקבע .}Rx=R .

אם רלוונטי( vi, )או R, v של descriptorבכל מקרה עדכן את ה-6.בהתאם.

Page 33: 1 תורת הקומפילציה 236360 הרצאה 11 יצירת הקוד Code Generation Aho, Lam, Sethi and Ullman – Chapter 8

33 33

דוגמאהקצאת רגיסטרים:

address descriptor register descriptor code generated statements

registers empty

a in R1, a in a, b in b, c in c, d in d, t in R2

R1 contains aR2 contains t

LD R1, aLD R2, bSUB R2, R1, R2

t := a – b

a in a, b in b, c in c, c in R3, d in d, t in R2, u in R1

R1 contains uR2 contains tR3 contains c

LD R3, cSUB R1, R1, R3

u := a – c

a in a, b in b, c in c, c in R3, d in d, t in R2, u in R1, v in R3

R1 contains uR2 contains tR3 contains v

ADD R3, R2, R1 v := t + u

a in a, b in b, c in c, d in d, c in R3, d in d, t in R2, d in R1, v in R3

R1 contains dR2 contains tR3 contains v

ADD R1, R1, R3ST d, R1

d := v + u

d := )a – b( + )a – c( + )a – c(

Page 34: 1 תורת הקומפילציה 236360 הרצאה 11 יצירת הקוד Code Generation Aho, Lam, Sethi and Ullman – Chapter 8

34

Register Allocation and Assignment

Register allocation.איזה ערכים יישמרו ברגיסטרים :

Register assignment.איזה ערך יישמר באיזה רגיסטר :

ההחלטות על מיקום ערכים ברגיסטרים הן מהחשובות באופטימיזציה של קוד.

הסיבה: פקודות הניגשות לרגיסטרים הן קצרות יותר ומהירות יותר.

-קשה )אפילו אם יש רק NP היא register allocationההחלטה על רגיסטר יחיד במכונה(. לכן משתמשים בהיוריסטיקות.

לעיתים ההיוריסטיקות מסתבכות עוד יותר בשל אילוצי חומרה. למשל מכונות מסויימות משתמשות בpairing-.

Mul R2,R3-מכניס את המכפלה של המספר ב R2-והמספר ב R3 מוגדרים מראש כצמד. R3 ו-R2 כאשר R2,R3אל הזוג

34

Page 35: 1 תורת הקומפילציה 236360 הרצאה 11 יצירת הקוד Code Generation Aho, Lam, Sethi and Ullman – Chapter 8

35

Register Allocation and Assignment

שתי גישות קיצוניות אפשריות:

כל רגיסטר יכול להכיל כל משתנה.הקצאה גלובלית:1.

לחלק את הרגיסטרים לקבוצות, כשלכל קבוצה אחראית על נושא 2.מסוים.

למשל, קבוצה אחת מחזיקה רק פוינטרים, אחרת מטפלתבחישובים אריתמטיים, שלישית משמשת רק ככתובות בסיס

, וכו'.(, עוד רגיסטר ישמש להחזרת פרמטר stack)למערכים, ל-מרוטינות וכיו"ב.

הגישה השלטת היא גישת ביניים: יש רגיסטרים ספציפיים שיוקצו , לשימוש כבסיס וכו', אבל הרוב מוקצים באופן גלובלי. stack pointerל-

35

Page 36: 1 תורת הקומפילציה 236360 הרצאה 11 יצירת הקוד Code Generation Aho, Lam, Sethi and Ullman – Chapter 8

36

הקצאת רגיסטרים גלובלית

עד עתה דיברנו רק על הקצאה בתוך בלוק בסיסי, והנחנו שערכם של משתנים נכתב חזרה לזיכרון בסוף כל בלוק.

נרצה לעיתים לבחור stores וה-loadsעל-מנת לחסוך חלק מה-משתנים שיש אליהם גישה תדירה ולהקצות להם רגיסטר שנשמר במעבר

בין בלוקים.

ההעדפה הראשונה ניתנת למשתנים "הכי פעילים" המופיעים בתוך הלולאות הפנימיות ביותר: אלו קטעי הקוד שמתבצעים )בד"כ( הכי

הרבה. נקצה רגיסטרים עבור משתנים אלה; השאר ישמשו להקצאה לוקלית

בבלוק.

ברגיסטר נעשית ע"י B מבלוק vהערכת התועלת של שמירת משתנה ספירה:

לכל מופע שלv-ב B.שבו ניתן להשתמש ברגיסטר נוסיף נקודה לכל מופע שלv-בבלוק עוקב שמשתמש בערך )בלי להציב ב v ערך

במעבר בין load ו-storeחדש( נוסיף שתי נקודות על כך שלא בצענו הבלוקים.

לאחר שנעריך תועלת לכל משתנה בלולאה הפנימית, נקצה רגיסטרים למשתנים שעבורם התועלת גבוהה ביותר.

Page 37: 1 תורת הקומפילציה 236360 הרצאה 11 יצירת הקוד Code Generation Aho, Lam, Sethi and Ullman – Chapter 8

37

Spilling-ו Graph Coloring

כאשר צריך להקצות רגיסטר וכל הרגיסטרים תפוסים, צריך לבחור ( את ערכו הקודם לשמירה בזיכרון. spillרגיסטר לשימוש, ולשפוך )

המצב האידיאלי הוא שמקצים רגיסטר חדש כאשר ערך ברגיסטר קודם . spilling"מת" וניתן להשתמש ברגיסטר הקודם ללא

-קשה.NP היא spillingמציאת הקצאת רגיסטרים שמביאה למינימום

לכן משתמשים בהיוריסטיקות הקשורות לצביעת גרפים.

נסתכל על תמונת הערכים החיים בתוכנית:

v1חי

v2חי

v3חי

v4חי

v5חי

v6חי

v7חי

v8חי

זמן ריצה

Page 38: 1 תורת הקומפילציה 236360 הרצאה 11 יצירת הקוד Code Generation Aho, Lam, Sethi and Ullman – Chapter 8

38

בניית גרף מתאים

נקצה צומת לכל משתנה, וקשת בין שני משתנים "מתנגשים".

צמתים מתנגשים אם יש חפיפה בזמן חייהם.

אם נקצה להם אותו משמעות:. spillרגיסטר אז יידרש

זמן ריצה

v1חי

v2חי

v3חי

v4חי

v5חי

v6חי

v7חי

v8חי

V1

V8

V2

V4

V7

V6

V5

V3

Page 39: 1 תורת הקומפילציה 236360 הרצאה 11 יצירת הקוד Code Generation Aho, Lam, Sethi and Ullman – Chapter 8

39

בניית גרף מתאים

נקצה צומת לכל משתנה, וקשת בין שני משתנים

"מתנגשים".

צמתים מתנגשים אם יש חפיפה בזמן חייהם.

אם נקצה להם אותו משמעות:. spillרגיסטר אז יידרש

V1

V8

V2

V4

V7

V6

V5

V3

רגיסטרים למשתנים כך ששני משתנים יוקצו לרגיסטרים k להקצות מטרתנו:שונים אם יש ביניהם קשת.

צבעים לצמתים כך שני צמתים שכנים יקבלו צבע kבעיית הצביעה:להקצות שונה.

. k>2-קשה עבור NP צביעה kבעיית ה-

אבל כאן מדובר בגרפים מאד ספציפיים: גרפי אינטרוואלים, שעבורם מציאת ניתנת לפיתרון יעיל. kצביעה ב-

controlמצד שני, התוכנית האמיתית אינה גרף אינטרוואלים פשוט, בשל ה-flow .האמיתי

Page 40: 1 תורת הקומפילציה 236360 הרצאה 11 יצירת הקוד Code Generation Aho, Lam, Sethi and Ullman – Chapter 8

40

היוריסטיקה

נמצא צביעה לגרף באופן הבא.1.

באופן איטרטיבי נעיף מהגרף כל 2. )עם כל kצומת שדרגתה קטנה מ-

קשתותיה(.

הסבר: לא משנה אילו צבעים 3.נבחר לצמתים האחרים, תמיד

נוכל לצבוע צומת זאת בצבע חוקי.

V1

V8

V2

V4

V7

V6

V5

V3

, או עם גרף ריק. kנשארנו עם צמתים שכולם מדרגה גדולה או שווה ל-4.

אם הגרף ריק, נחזיר את הצמתים שהעפנו אחת אחת ונצבע אותן. אחרת, 5.

נבחר צומת כלשהו ונעיף אותו מהגרף. המשמעות: משתנה זה לא יקבל 6.רגיסטר אלא יוקצה מהזיכרון. נחזור על שלב זה עד שייוצר צומת עם דרגה

ואז נתחיל מהתחלה.kקטנה מ-

Page 41: 1 תורת הקומפילציה 236360 הרצאה 11 יצירת הקוד Code Generation Aho, Lam, Sethi and Ullman – Chapter 8

41

היוריסטיקה

נמצא צביעה לגרף באופן הבא.1.

באופן איטרטיבי נעיף מהגרף כל 2. )עם כל kצומת שדרגתה קטנה מ-

קשתותיה(.

הסבר: לא משנה אילו צבעים 3.נבחר לצמתים האחרים, תמיד

נוכל לצבוע צומת זאת בצבע חוקי.

V1

V8

V2

V4

V7

V6

V5

V3

, או עם גרף ריק. kנשארנו עם צמתים שכולם מדרגה גדולה או שווה ל-4.

אם הגרף ריק, נחזיר את הצמתים שהעפנו אחת אחת ונצבע אותן. אחרת, 5.

נבחר צומת כלשהו ונעיף אותו מהגרף. המשמעות: משתנה זה לא יקבל 6.רגיסטר אלא יוקצה מהזיכרון. נחזור על שלב זה עד שייוצר צומת עם דרגה

ואז נתחיל מהתחלה.kקטנה מ-

הפעולה ההיוריסטית העיקרית כאן היא בחירת הצומת

spills, והיא קובעת כמה 6להעיף בעת ביצוע שלב באמת יהיו.

Page 42: 1 תורת הקומפילציה 236360 הרצאה 11 יצירת הקוד Code Generation Aho, Lam, Sethi and Ullman – Chapter 8

42

שימו לב שלא השגנו פיתרון אופטימאלי

ראשית, יתכן שיש פיתרון אחר שבו מוותרים בהיוריסטיקה על צמתים . spillsאחרים ומתקבלים פחות

שנית, יצרנו את הגרף מתוך הנחות שמרניות של חפיפה בזמן החיים של משתנים. תיתכנה תלויות של גרף הזרימה כך ששני משתנים לעולם לא

באמת חיים יחד, אבל אנחנו לא מודעים לכך בניתוח השמרני הפשוט.

וכל spillsאבל – אם מצאנו צביעה מלאה של הגרף, כלומר, לא דרושים המשתנים יכולים לחיות ברגיסטרים, אז הפיתרון שמצאנו הוא )כמובן(

אופטימאלי.

Page 43: 1 תורת הקומפילציה 236360 הרצאה 11 יצירת הקוד Code Generation Aho, Lam, Sethi and Ullman – Chapter 8

43

יצירת קודלסיכום:

(back-endמעבר משפת ביניים לשפת מטרה )

מכונת מטרה לדוגמא. .אורך הקוד ויעילותו תלוי בניצול יעיל של הרגיסטרים

ייצור קוד לניהול רשומות הפעלה

2ת, control flow graphבלוקים בסיסיים, של משנים. ח3יו

טרנספורמציות פשוטות בתוך בלוקים בסיסיים.

ייצור קוד תוך כדי מעקב על מיקום המשתנים בזיכרון וברגיסטרים.

הקצאת רגיסטרים.