هل من المنطقي أن يمرر المترجم بهيكل مثل هذا في سجل وحدة المعالجة المركزية إلى وظيفة؟

StackOverflow https://stackoverflow.com/questions/4213107

سؤال

أود أن أعرف ما إذا كان هناك نوع من الهيكل يحتوي على أكثر من بدائي واحد ، لكن حجمه الإجمالي أقل من أو يساوي حجم سجل وحدة المعالجة المركزية واحدة مثل سجل 4 بايت ، فهل من المنطقي أن يضعه في أي وقت مضى في أحد هذه السجلات الأربعة بايت عند تمريرها بالقيمة أو الإشارة إلى وظيفة بدلاً من عمل نسخة منها على كومة Callee أو تمرير مؤشر إليها بشكل عام عند تمرير شيء أكثر من مجرد بدائية لوظيفة مثل صفيف أو هيكل سوف يمر في سجل وحدة المعالجة المركزية في متناول يدي؟

عينة من هذا الهيكل:

struct sample{
 public:
  char char1;
  char char2;
};

عينة من تمرير الهيكل إلى وظيفة:

void someFunc(const sample input){
 //whatever
}
void someFunc(sample input){
 //whatever
}
void someFunc(sample & input){
 //whatever
}
void someFunc(const sample & input){
 //whatever
}
هل كانت مفيدة؟

المحلول

نعم. لدى العديد من المترجمين كلمة رئيسية أو سمة نوع يمكنك استخدامها لتحديد أن البنية يجب أن يتم تمريرها في السجلات بدلاً من المكدس. إنه أكثر شيوعًا على المعالجات التي لديها العديد من السجلات وخطوط الأنابيب العميقة ، مثل PowerPC ، ويمكن أن تكون تحسناً هائلاً في الأداء في البنية حيث تتسبب كتابة قيمة للذاكرة ثم قراءتها مرة أخرى على الفور على وجود كشك خط أنابيب.

عادةً ما لا تستخدمه فقط للهيكل الذي يكون بنفس حجم السجل الأصلي. على وجه الخصوص ، من المفيد على المعالجات التي لديها سجلات SIMD واسعة ، والتي يمكن أن تمر 16 بايت في وقت أو أكثر. هذا من شأنه أن يتيح لك تمرير (على سبيل المثال) متجه 4 أبعاد (أربعة عوامات) في سجل واحد. نظام AMD V هو مثال على X86 ABI الذي يسمح بذلك.

مثال مختلف هو سمة نوع D64_ABI من GCC ، والتي تخبر PowerPC بتمرير بنية على السجلات حيثما أمكن ، بدلاً من المكدس. (هذا جزء من داروين أبي).

typedef struct {
    int          a;
    float        f;
    char         c;
} __attribute__ ((d64_abi)) Thingy;

Thingy foo( Thingy t );

في الحالة المذكورة أعلاه ، فإن دعوة Foo تمر عبر Thingy في سجل عائم واحد وسجلين Int ، بدلاً من كتابته إلى المكدس وقراءته مرة أخرى مرة أخرى. تعود قيمة الإرجاع إلى السجلات بنفس الطريقة.

لم أر أبدًا برنامجًا برمجيًا يقوم بذلك تلقائيًا ، دون إخبارك به ، لكن من الممكن وجود واحد.

نصائح أخرى

هذا محدد في تطبيق الواجهة الثنائية (ABI) من بيئة التنفيذ الخاصة بك. لا يقول المعيار أي شيء عن سجلات المعالج عندما يتم استدعاء وظيفة ، لذلك من القانوني إنشاء بيئة يتم فيها تعبئة الهياكل الصغيرة في سجل معالج واحد.

بالنسبة للجزء المرجعي ، من المحتمل جدًا أن يتم تمريرها كمؤشرات على أي حال ، لأنه عندما يتم أخذ عنوان المرجع داخل الوظيفة المسمى ، يجب حلها إلى عنوان الكائن المشار إليه.

في بعض البنى (مثل i386 ، أعرف أنها قديمة ، لكن هذا ما نشأت معه ؛) من المنطقي بالتأكيد تمريره في السجل ، لأن الدفع والظهور من المكدس يستغرق الكثير (على سبيل المثال بين 3-6 مرات المزيد) دورات وحدة المعالجة المركزية كما تم المرور حسب السجل. لذلك يقوم المترجم بعمل جيد لتحسين ذلك.

أستطيع أن أتخيل أن هناك بنيات أخرى لا يهم. أو إذا كانت السجلات قيد الاستخدام لتحسينات أخرى تسفر عن مزيد من التحسن ، فليس من المنطقي استخدامها لهذا الغرض.

ما هي البنية التي تستخدمها/تستهدفها ، أم تسأل بشكل عام؟

أعتقد أن هناك مجمعين سوف يمرون القرون في السجلات ، حتى لو كانوا كذلك structس.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top