Ist es für einen Compiler immer sinnvoll, eine Struktur wie diese in einem CPU-Register an eine Funktion zu übergeben?

8

Ich würde gerne wissen, ob eine Art von Struktur mehr als ein Primitiv enthält, aber seine Gesamtgröße ist kleiner oder gleich der Größe eines einzelnen CPU-Registers wie ein 4-Byte-Register, macht es für einen Compiler Sinn um es in eines dieser 4-Byte-Register zu setzen, wenn es nach Wert oder Verweis auf eine Funktion übergeben wird, anstatt es auf dem Aufrufstapel zu kopieren oder einen Zeiger darauf zu übergeben, und im allgemeinen wenn mehr als ein einzelnes Primitiv an etwas übergeben wird eine funktion wie ein array oder eine struktur würde in einem cpu-register passieren, die sich als praktisch erweisen?

Beispiel einer solchen Struktur:

%Vor%

Beispiel für das Übergeben der Struktur an eine Funktion:

%Vor%     
Pooria 18.11.2010, 09:04
quelle

4 Antworten

4

Ja. Viele Compiler verfügen über ein spezielles Schlüsselwort- oder Typattribut, mit dem Sie angeben können, dass eine Struktur in Registern und nicht auf dem Stapel übergeben werden soll. Es ist häufiger auf Prozessoren, die viele Register und tiefe Pipelines haben, wie der PowerPC, und kann eine enorme Leistungsverbesserung in Architekturen sein, bei denen ein Wert in den Speicher geschrieben und dann sofort wieder zurückgelesen wird, was einen Pipeline-Stillstand verursacht.

Normalerweise würden Sie es nur für eine Struktur verwenden, die die gleiche Größe wie ein natives Register hat. Insbesondere ist es nützlich bei Prozessoren, die breite SIMD-Register haben, die 16 Bytes gleichzeitig oder mehr durchlaufen können. Das würde Sie (zum Beispiel) einen 4-dimensionalen Vektor (vier Floats) auf einem Register passieren lassen. AMDs System V ist ein Beispiel für einen x86 ABI, der dies erlaubt.

Ein anderes Beispiel ist GCCs Attribut d64_abi type, das einem PowerPC anweist, eine Struktur in Registern zu übergeben, wo dies möglich ist, und nicht auf dem Stapel. (Dies ist Teil der Darwin ABI ).

%Vor%

Im obigen Fall würde ein Aufruf von Foo den Thingy auf einem Float-Register und zwei int-Registern übergeben, anstatt es auf den Stack zu schreiben und es gleich wieder zurück zu lesen. Der Rückgabewert kommt in den Registern auf die gleiche Weise zurück.

Ich habe noch nie einen Compiler gesehen, der das automatisch macht, ohne es zu sagen, aber es ist möglich, dass es einen gibt.

    
Crashworks 18.11.2010, 09:28
quelle
5

Dies ist in der Anwendungs-Binärschnittstelle (ABI) Ihrer Ausführungsumgebung definiert. Der Standard sagt nichts über Prozessorregister aus, wenn eine Funktion aufgerufen wird, daher ist es legal, eine Umgebung zu erstellen, in der kleine Strukturen in ein einziges Prozessorregister gepackt sind.

Für den Referenzteil werden sie sehr wahrscheinlich sowieso als Zeiger übergeben, da innerhalb der aufgerufenen Funktion die Adresse einer Referenz genommen werden muss, die auf die Adresse des referenzierten Objekts aufgelöst werden muss.

    
Rudi 18.11.2010 09:17
quelle
3

Auf bestimmten Architekturen (wie i386, ich weiß, es ist alt, aber das ist es, wofür ich aufgewachsen bin;) ist es sinnvoll, es in einem Register zu übergeben, da das Schieben und Puffen viel mehr kostet (sagen wir zwischen 3 -6-mal mehr) CPU-Zyklen als Register passieren. Also würde ein Compiler eine gute Arbeit dafür tun, zu optimieren.

Ich kann mir vorstellen, dass es andere Architekturen gibt, bei denen es keine Rolle spielt. Oder wenn die Register für andere Optimierungen verwendet werden, die zu mehr Verbesserung führen, ist es nicht sinnvoll, sie dafür zu verwenden.

Welche Architektur verwenden Sie / Targeting oder fragen Sie im Allgemeinen?

    
thomaspaulb 18.11.2010 09:17
quelle
1

Ich denke, es gibt Compiler, die PODs in Registern übergeben, auch wenn sie struct s sind.

    
sbi 18.11.2010 09:18
quelle