Como evitar que o gcc otimize algumas instruções em C?

107

Para tornar uma página suja (ativando a parte suja na entrada da tabela de páginas), toco os primeiros bytes da página assim:

pageptr[0] = pageptr[0];

Mas, na prática, o gcc ignorará a instrução eliminando o armazenamento morto. Para evitar que o gcc o otimize, reescrevo a instrução da seguinte maneira:

volatile int tmp;
tmp = pageptr[0];
pageptr[0] = tmp;

Parece que o truque funciona, mas um tanto feio. Gostaria de saber se existe alguma diretiva ou sintaxe que tenha o mesmo efeito? E não quero usar -O0flag, pois trará grande penalidade de desempenho também.

ZelluX
fonte
8
@Mark -O0 interromperá a otimização, mas também diminuirá o desempenho do programa. Eu só quero evitar a otimização deste snippet de código: P
ZelluX
Gostaria de acrescentar que, no passado, mesmo o uso -O0não impedia a "otimização" de código morto, por exemplo, quando o GCC detecta que algum código não tem efeito, ele simplesmente o remove. AFAIK esta é uma fase antes -O0... Mas essa é apenas a minha experiência
smoothware

Respostas:

91

Desativar a otimização corrige o problema, mas é desnecessário. Uma alternativa mais segura é tornar ilegal para o compilador otimizar o armazenamento usando o volatilequalificador de tipo.

// Assuming pageptr is unsigned char * already...
unsigned char *pageptr = ...;
((unsigned char volatile *)pageptr)[0] = pageptr[0];

O volatilequalificador de tipo instrui o compilador a ser estrito quanto aos armazenamentos e cargas de memória. Um dos objetivos do volatileé permitir que o compilador saiba que o acesso à memória tem efeitos colaterais e, portanto, deve ser preservado. Nesse caso, o armazenamento tem o efeito colateral de causar uma falha de página e você deseja que o compilador preserve a falha de página.

Desta forma, o código ao redor ainda pode ser otimizado, e seu código é portável para outros compiladores que não entendem GCC #pragmaou __attribute__sintaxe.

Dietrich Epp
fonte
2
Eu diria que isso é preferível a desligar as otimizações. Você ainda pode se beneficiar de outras otimizações usando este método.
Ben S
3
A solução de Dietrich Epp não está funcionando no compilador ARM4.1 . Mesmo a solução do ZelluX não está funcionando. O método alternativo para fazer isso funcionar para ARM4.1 está na solução do ZelluX, tornar ' temp ' uma variável global volátil .
Oculus Dexter
1
Isso é muito ruim para o referido compilador.
Alexey Frunze
1
@Shocker: GCC ainda pode otimizar a variável sem otimizar o acesso real à memória. Essas são questões diferentes.
Dietrich Epp de
2
@jww: esse uso se encaixa com o que é descrito naquela postagem do blog. volatilesignifica que o acesso à memória deve ocorrer conforme escrito, que é exatamente o que queremos. Em outras palavras, pensamos cuidadosamente sobre isso e significa o que pensamos que significa.
Dietrich Epp
184

Você pode usar

#pragma GCC push_options
#pragma GCC optimize ("O0")

your code

#pragma GCC pop_options

para desabilitar otimizações desde o GCC 4.4.

Consulte a documentação do GCC se precisar de mais detalhes.

Arado
fonte
3
É importante notar, entretanto, que isso só funciona em funções inteiras, não em instruções específicas: gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc/… "Cada função que é definida após este ponto é como se um atributo (( Optimize ("STRING"))) foi especificado para essa função. ".
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
134

Em vez de usar os novos pragmas, você também pode usar __attribute__((optimize("O0")))para suas necessidades. Isso tem a vantagem de se aplicar apenas a uma única função e não a todas as funções definidas no mesmo arquivo.

Exemplo de uso:

void __attribute__((optimize("O0"))) foo(unsigned char data) {
    // unmodifiable compiler code
}
FRob
fonte
3
E se eu não estiver usando uma -Olevelopção, mas tiver usado as opções individuais que ela ativa separadamente? (No meu caso, não consigo determinar qual é a opção de otimização individual que está quebrando o código) .
user2284570