Skip to content

مقدمه

کامپایلر یکی از جالب ترین چیز هایی هست که تا حالا تو زندگیم باهاش برخورد کردم! البته این برای چند مدت اخیر هست که بیشتر از flag های کامپایلر استفاده می کنم و بیشتر متوجه عمق این ابزار میشم. چیزی که تازگی باهاش برخورد داشتم، بهینه سازی کامپایلر هست. کامپایلر می تونه بعضی کد ها و منطق ها رو بهتر به زبان ماشین پیاده سازی کنه و حتی ممکن هست که کاربر متوجه این موضوع نشه مگر اینکه شروع کنه به دیباگ کردن کد و بررسی اسمبلی که کامپایلر تولید کرده و اونجاست که احتمالا متوجه این موضوع میشه.

تنظیمات بهینه سازی در gcc و ...

توی gcc و ++g میشه با فلگ Ox و دادن مقدار های 0 تا 3 به جای x،خروجی رو بهینه کرد.

bash
gcc -O3 main.cpp -o main

این کامند ، کد ما رو به بهینه ترین شکل ممکن کامپایل میکنه و هر چی عدد رو کاهش بدیم ، این بهینه سازی کاهش پیدا میکنه.

bash
gcc -O0 main.cpp -o main

در این عبارت ، اگر اسمبلی رو از کامپایلر بگیریم متوجه میشم که تمامی عبارت ها به عبارت های ساده اسمبلی تبدیل شدن و هیچ بهینه سازی وجود نداره.

سوال جالب

خب اصلا چرا باید کدمون رو در کمترین حالت بهینگی کامپایل کنیم. تنها دلیلی که بهش برخورد کردم، بررسی کد داخل دیباگر هست. یک مثال هم آوردم که خیلی جالبه، درسته که کدی ساده ای هست ولی اگر یک بار با بهینگی سطح 3 و بار دیگر با بهینگی سطح 0 کامپایل بشه،داخل gdb نتایج متفاوتی از خودش موقع trace کردن نشون میده(همچنان خروجیش یکسان و درسته !) من یک کدی رو این پایین برای شما قرار میدم تا تست کنید.

cpp
#include <stdio.h>

static inline int foo(int x) {
    int y = x * 2;
    int z = y + 3;
    return z;
}

int main() {
    int a = 5;
    int b = foo(a);
    int c = foo(b);

    printf("%d\n", c);
    return 0;
}

اگر این کد رو با بهینه ساز سطح 3 کامپایل کنید ، از قبل جواب این معادله رو بدست میاره. و موقع استفاده gdb متوجه میشید که از روی بعضی عبارات میپره و اون ها رو اجرا نمیکنه. ولی در هنگام استفاده از بهینه سازی سطح 0 ، gdb به خوبی تک تک این ها رو بدست میاره. این یک مثال خیلی ساده هست ولی در یک کد خیلی بزرگ تر احتمالا مشکلات خیلی بیشتری موقع دیباگ کردن به وجود بیاد.