Questo è relativo a How to force const propagation through an inline function? Clang ha un assemblatore integrato; e non usa l'assemblatore del sistema (che è spesso GNU AS (GAS)). Non-Clang ha fatto presto i calcoli matematici, e tutto "ha funzionato".Forza Clang per "eseguire matematica precocemente" su valori costanti
Dico "in anticipo" perché @ n.m. obiettato a descriverlo come "la matematica eseguita dal preprocessore". Ma l'idea è che il valore sia noto al momento della compilazione e dovrebbe essere valutato in anticipo, come quando il preprocessore valuta uno #if (X % 32 == 0)
.
Sotto, Clang 3.6 si lamenta di aver violato un vincolo. Appare la costante non viene propagata:
$ export CXX=/usr/local/bin/clang++
$ $CXX --version
clang version 3.6.0 (tags/RELEASE_360/final)
Target: x86_64-apple-darwin12.6.0
...
$ make
/usr/local/bin/clang++ -DNDEBUG -g2 -O3 -Wall -fPIC -arch i386 -arch x86_64 -pipe -Wno-tautological-compare -c integer.cpp
In file included from integer.cpp:8:
In file included from ./integer.h:7:
In file included from ./secblock.h:7:
./misc.h:941:44: error: constraint 'I' expects an integer constant expression
__asm__ ("rolb %1, %0" : "+mq" (x) : "I" ((unsigned char)(y%8)));
^~~~~~~~~~~~~~~~~~~~
./misc.h:951:44: error: constraint 'I' expects an integer constant expression
...
Le funzioni specializzazioni modello sopra sono inlined:
template<> inline byte rotrFixed<byte>(byte x, unsigned int y)
{
// The I constraint ensures we use the immediate-8 variant of the
// shift amount y. However, y must be in [0, 31] inclusive. We
// rely on the preprocessor to propoagte the constant and perform
// the modular reduction so the assembler generates the instruction.
__asm__ ("rorb %1, %0" : "+mq" (x) : "I" ((unsigned char)(y%8)));
return x;
}
Essi vengono eseguiti con un valore const, quindi la quantità di rotazione è noto al momento della compilazione . Un tipico chiamante potrebbe essere simile:
unsigned int x1 = rotrFixed<byte>(1, 4);
unsigned int x2 = rotrFixed<byte>(1, 32);
Nessuno di questi [discutibili] trucchi sarebbe necessario se GCC o Clang fornito un intrinseco per eseguire le rotate in near constant time. Mi accontenterei persino di "eseguire la rotazione" poiché non hanno nemmeno quello.
Qual è il trucco necessario per far riprendere Clang eseguendo la pre-elaborazione del valore const?
lettori più attenti riconosceranno rotrFixed<byte>(1, 32)
potrebbe essere un comportamento indefinito se si utilizza un tradizionale C/C++ ruotare. Quindi passiamo all'assemblaggio per evitare le limitazioni di C/C++ e godetevi l'1 speedup delle istruzioni.
Un curioso lettore potrebbe chiedersi perché lo faremmo. I crittografi chiamano le specifiche e, a volte, queste specifiche non sono in sintonia con l'hardware sottostante o con gli enti standard. Piuttosto che modificare le specifiche del cryptographer, tentiamo di fornirle testualmente per rendere più semplici i controlli.
Un bug è stato aperto per questo problema: LLVM Bug 24226 - Constant not propagated into inline assembly, results in "constraint 'I' expects an integer constant expression".
Non so cosa garantisce Clang, ma so che il compilatore e l'assemblatore integrato dichiarano di essere compatibili con l'assemblatore di GCC e GNU. E GCC e GAS forniscono la propagazione del valore costante.
Continui a parlare dell'aritmetica del preprocessore, ma non ci sono costanti # define'd ovunque nel codice. –
È possibile utilizzare l'assemblatore di sistema tramite '-no-integrated-as'. – Thomas
Se 'y' è noto al momento di comoile, perché non renderlo un parametro template? –