Bereitstellung von 32-Byte-Ausrichtung kostet zusätzliche Anweisungen (weil der ABI nur 16-Byte-Ausrichtung garantiert; sehen Sie sich die ASM für die Version mit alignas(32)
oder __attribute__((aligned(32)))
an). Natürlich tut der Compiler es nicht, wenn Sie nicht danach fragen, weil es nicht frei ist. (Siehe auch gcc's -mpreferred-stack-boundary
which controls this, und das x86 Tag-Wiki für Links zu ABI-Dokumenten).
double localvar[4];
muss nur 8-Byte ausgerichtet sein, damit jedes Element natürlich ausgerichtet ist. Die SysV x86-64 ABI garantiert eine 16-Byte-Ausrichtung für C99-Arrays variabler Größe. Ich bin mir nicht sicher, ob normale Kompilierzeit-Konstanten große Arrays 16-B-Ausrichtung standardmäßig erhalten oder nicht.
Aktuelle Versionen von gcc jedoch aus irgendeinem Grund den Stack auf 32B in einer Testfunktion ausrichten, die __m256d
lokale Variablen hat. Bei -O3
verschüttet es sie nicht auf den Stapel, also sind sie verschwendet (abgesehen davon, dass Buggy-Code wie dieser funktioniert). Die Tatsache, dass gcc dieses Zeug nicht entfernt, ist eine verpasste Optimierung. (Es wird bei -O0
benötigt, wo gcc alles zum Speicher verschüttet.)
Da meine Version Ihrer Testfunktion (die tatsächlich kompiliert) keine anderen Einheimischen hat, ist das Array der Doppelgänger auch 32B-ausgerichtet. Vermutlich gliedern Sie es in einen Aufrufer, der andere Einheimische hat, und das führt zu einer anderen Ausrichtung für das Array.
Here's the code on the Godbolt compiler explorer:
extern void use_buffer(double*);
// static inline
void no_alignment(const double *phi){
double localvar[4];
__m256d var = _mm256_load_pd (phi);
__m256d res = _mm256_mul_pd(var, var);
_mm256_storeu_pd (localvar, res); // use an unaligned store since we didn't request alignment for the buffer
use_buffer(localvar);
}
lea r10, [rsp+8] // save old RSP (in a clumsy way)
and rsp, -32 // truncate RSP to the next 32B boundary
push QWORD PTR [r10-8] // save more stuff
push rbp
mov rbp, rsp
push r10
sub rsp, 40
... vmovupd YMMWORD PTR [rbp-48], ymm0 ... // function body
add rsp, 40
pop r10
pop rbp
lea rsp, [r10-8]
Aus diesem Grund ist der Code, wenn es inlined nicht zur Arbeit passiert. Obwohl es merkwürdig ist, dass es auch ohne das inline
Schlüsselwort nicht inline wird, es sei denn Sie kompilierten ohne Optimierung oder Sie verwendeten static
nicht, um dem Compiler mitzuteilen, dass eine separate Definition nicht benötigt wurde.
Durch Zufall, schätze ich. – MikeCAT
Bitte versuchen Sie [diesen Code] (http://www.tutorialspoint.com/compile_c_online.php?PID=0Bw_CjBb95KQMNFRDcGd3NmxDQmc) mit zusätzlichen lokalen Variablen in Ihrer Umgebung. Wird das Array immer noch ausgerichtet sein? – MikeCAT
Standard C erfordert keine Ausrichtung von lokalen Variablen. Sie müssen Compiler-spezifische Erweiterungen wie die von Ihnen erwähnte verwenden, um das gewünschte Ergebnis zu erhalten. –