درهم کردن ثابت
در هم کردن ثابت و ترویج ثابت از بهینه سازی های مرتبط به هم کامپایلر هستند که توسط بسیاری از کامپایلرهای مدرن مورد استفاده قرار می گیرند. یک شکل پیشرفته از ترویج ثابت که با عنوان ترویج ثابت شرطی پراکنده شناخته می شود، می تواند با دقت بیشتری ثابت ها را رواج دهد و همزمان کد مرده را حذف کند.
در هم کردن ثابت
در هم کردن ثابت فرایند تشخیص و ارزیابی عبارات ثابت در زمان کامپایل ، به جای محاسبه آن ها در زمان اجرا است. ترم ها در عبارات ثابت معمولاً مقادیر ساده هستند، مانند عدد صحیح 2
، اما ممکن است متغیرهایی باشند که مقادیر آن ها در زمان کامپایل شناخته شده است. جمله زیر را در نظر بگیرید:
i = 320 * 200 * 32;
در واقع بیشتر کامپایلرها دو دستورالعمل ضرب و یک ذخیره سازی برای این عبارت ایجاد نمی کنند. در عوض، آن ها ساختارهایی مانند این ها را شناسایی کرده و مقادیر محاسبه شده را در زمان کامپایل جایگزین می کنند (در این مثال 2،048،000).
در هم کردن ثابت می تواند از شناسه های حسابی استفاده کند. اگر x
عدد باشد ، مقدار 0 * x
صفر است حتی اگر کامپایلر مقدار x
را نداند (توجه داشته باشید که این مورد برای ممیز شناورهای IEEE معتبر نیست زیرا x
می تواند بی نهایت باشد یا عدد نباشد. با این حال، برخی از زبان ها که از کارایی مانند GLSL پشتیبانی می کنند، این امر را برای ثابت ها اجازه می دهند که بعضی مواقع می تواند باعث بروز اشکالاتی شود).
در هم کردن ثابت ممکن است برای مثال های غیر عددی نیز استفاده شود. برای به هم چسباندن رشته ها و رشته های ثابت نیز می توان از درهم کردن ثابت استفاده کرد. کد هایی مانند "abc" + "def"
ممکن است با "abcdef"
جایگزین شود.
در هم کردن ثابت و کامپایل کردن میانی
در پیاده سازی یک کامپایلر میانی باید دقت شود که رفتار عملیات حسابی بر روی معماری میزبان مطابق با معماری هدف باشد، زیرا در غیر این صورت فعال کردن قابلیت در هم کردن ثابت باعث تغییر رفتار برنامه می شود. این مورد در خصوص عملیات ممیز شناور از اهمیت ویژه ای برخوردار است، که پیاده سازی دقیق آن ممکن است بسیار متفاوت باشد.
ترویج ثابت
ترویج ثابت فرایند جایگزینی مقادیر ثابت های شناخته شده در عبارات در زمان کامپایل است. چنین ثابت هایی شامل مواردی است که در بالا تعریف شده است ، به علاوه ی توابع ذاتی که به مقادیر ثابت اعمال می شوند. شبه کد زیر را در نظر بگیرید:
int x = 14;
int y = 7 - x / 2;
return y * (28 / x + 2);
با ترویج x به دست می آید:
int x = 14;
int y = 7 - 14 / 2;
return y * (28 / 14 + 2);
با ادامه ی ترویج کد زیر به دست می آید (که احتمالاً با حذف کد مرده x و y بهینه می شود.)
int x = 14;
int y = 0;
return 0;
ترویج ثابت در کامپایلرها با استفاده از نتایج آنالیز رسیدن به تعریف پیاده سازی شده است. اگر همه رسیدن به تعریف های متغیر، یک تخصیصی باشد که یک ثابت را به متغیر اختصاص می دهد، در آن صورت متغیر یک مقدار ثابت دارد و می تواند با آن ثابت جایگزین شود.
ترویج ثابت همچنین می تواند باعث شود که شاخه های مشروط به یک یا چند جمله بدون شرط ساده شوند، وقتی عبارت شرطی می تواند در زمان کامپایل به صحیح یا غلط ارزیابی شود تا تنها نتیجه ممکن را تعیین کند.
بهینه سازی در عمل
در هم کردن و ترویج ثابت معمولاً برای رسیدن به تعداد زیادی ساده سازی و کاهش، با استفاده پشت سر هم آن ها به طور حلقه ای تا زمانی که تغییر جدیدی رخ ندهد ، به کار می روند. این شبه کد را در نظر بگیرید:
int a = 30;
int b = 9 - (a / 5);
int c;
c = b * 4;
if (c > 10) {
c = c - 10;
}
return c * (60 / a);
با یک بار استفاده از ترویج ثابت و به دنبال آن در هم کردن ثابت، به دست می آید:
int a = 30;
int b = 3;
int c;
c = b * 4;
if (c > 10) {
c = c - 10;
}
return c * 2;
تکرار هر دو مرحله برای دو بار، نتیجه می دهد:
int a = 30;
int b = 3;
int c;
c = 12;
if (true) {
c = 2;
}
return c * 2;
همانطور که a
و b
به ثابت ها ساده شده اند و مقادیر آنها در هر جا که استفاده شده اند جایگزین شده، کامپایلر اکنون حذف کد مرده را برای دور ریختن آنها اعمال می کند و کد را کاهش می دهد:
int c;
c = 12;
if (true) {
c = 2;
}
return c * 2;
در کد بالا ، به جای true
بسته به چارچوب کامپایلر ، می توانست 1 یا هر ساختار بولین دیگری باشد. با ترویج ثابت سنتی، ما فقط به همین مقدار بهینه سازی خواهیم رسید. این نمی تواند ساختار برنامه را تغییر دهد. یک بهینه سازی مشابه دیگر وجود دارد ، به نام ترویج ثابت شرطی پراکنده ، که شاخه مناسب را بر اساس if-condition
انتخاب می کند. کامپایلر اکنون می تواند تشخیص دهد که دستور if
همیشه مقدار صحیح ارزیابی می شود ، c
می تواند از بین ببرد و کد را حتی بیشتر کاهش دهد:
return 4;
اگر این شبه کد بدنه یک تابع را تشکیل دهد، کامپایلر می تواند از دانشی که در مورد خروجی آن (یعنی عدد صحیح ثابت 4
) دارد، برای از بین بردن صدا زدن های غیر ضروری تابع استفاده کند و در نتیجه باعت کارایی بیشتر شود.
همچنین ببینید
منابع
- ↑ Steven Muchnick; Muchnick and Associates (15 August 1997). Advanced Compiler Design Implementation. Morgan Kaufmann. ISBN 978-1-55860-320-2.
- ↑ Wegman, Mark N; Zadeck, F. Kenneth (April 1991), "Constant Propagation with Conditional Branches", ACM Transactions on Programming Languages and Systems, 13 (2): 181–210, doi:10.1145/103135.103136
مطالعه ی بیشتر
- Muchnick, Steven S. (1997), Advanced Compiler Design and Implementation, Morgan Kaufmann, ISBN 9781558603202