2015-11-28 18 views
13

In Chandler Carruth's CppCon 2015 talk introduce due funzioni magiche per sconfiggere l'ottimizzatore senza penalizzazioni extra."Escape" e "Clobber" equivalenti in MSVC

Per avere un riferimento, qui le funzioni (utilizzando assembly inline in stile GNU):

void escape(void* p) 
{ 
    asm volatile("" : : "g"(p) : "memory"); 
} 

void clobber() 
{ 
    asm volatile("" : : : "memory"); 
} 

Funziona su qualsiasi compilatore che supporta il montaggio in stile GNU linea (GCC, Clang, compilatore di Intel, forse altri) . Tuttavia, egli menziona che non funziona in MSVC.

Esaminando Google Benchmark's implementation, sembra che utilizzino un reinterpretazione del cast in un volatile const char& e lo trasferisca a una funzione nascosta in un'unità di traduzione diversa su compilatori non-gcc/clang.

template <class Tp> 
inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) { 
    internal::UseCharPointer(&reinterpret_cast<char const volatile&>(value)); 
} 

// some other translation unit 
void UseCharPointer(char const volatile*) {} 

Tuttavia, ci sono due problemi che ho con questo:

  1. sto potenzialmente incorrere in una chiamata di funzione
  2. C'è la possibilità di un "intelligente" link-tempo ottimizzatore potrebbe riconoscere UseCharPointer è piccolo, lo integra, quindi elimina tutto il codice che volevo tenuto in giro, o un ottimizzatore "intelligente" potrebbe essere autorizzato a eseguire altri riordini che non desidero.

Esiste un equivalente di livello inferiore in MSVC alle funzioni di assieme stile GNU? O è questo il meglio che ottiene su MSVC?

risposta

4

Mentre io non so di un trucco di montaggio equivalente per MSVC, Facebook utilizza il seguente nella loro biblioteca di riferimento Folly:

/** 
* Call doNotOptimizeAway(var) against variables that you use for 
* benchmarking but otherwise are useless. The compiler tends to do a 
* good job at eliminating unused variables, and this function fools 
* it into thinking var is in fact needed. 
*/ 
#ifdef _MSC_VER 

#pragma optimize("", off) 

template <class T> 
void doNotOptimizeAway(T&& datum) { 
    datum = datum; 
} 

#pragma optimize("", on) 

#elif defined(__clang__) 

template <class T> 
__attribute__((__optnone__)) void doNotOptimizeAway(T&& /* datum */) {} 

#else 

template <class T> 
void doNotOptimizeAway(T&& datum) { 
    asm volatile("" : "+r" (datum)); 
} 

#endif 

Here is a link to code on GitHub.