Ele sempre faz sentido para um compilador para passar de uma estrutura como essa em um registro de cpu para uma função?

StackOverflow https://stackoverflow.com/questions/4213107

Pergunta

Eu gostaria de saber se algum tipo de estrutura contém mais de uma primitiva, mas o tamanho total é menor ou igual ao tamanho de um único registro da cpu como um 4-registo de byte, ele sempre faz sentido para um compilador para colocá-lo em um dos 4 bytes de registradores de quando em passagem por valor ou referência a uma função em vez de fazer uma cópia da mesma em que o receptor pilha ou passar um ponteiro para ele e, em geral, quando passar, algo mais do que uma única primitiva de uma função como uma matriz ou uma estrutura de passagem de um registro de cpu sempre vem a calhar?

exemplo de tal estrutura:

struct sample{
 public:
  char char1;
  char char2;
};

exemplo de passar a estrutura de uma função:

void someFunc(const sample input){
 //whatever
}
void someFunc(sample input){
 //whatever
}
void someFunc(sample & input){
 //whatever
}
void someFunc(const sample & input){
 //whatever
}
Foi útil?

Solução

Sim. Muitos compiladores têm um atributo de palavra -chave ou tipo especial que você pode usar para especificar que uma estrutura deve ser passada nos registros e não na pilha. É mais comum em processadores que possuem muitos registros e pipelines profundos, como o PowerPC, e podem ser uma tremenda melhoria de desempenho nas arquiteturas, onde escrever um valor na memória e depois lê -lo novamente causa uma barraca de pipeline.

Normalmente, você o usaria apenas para uma estrutura do mesmo tamanho de um registro nativo. Em particular, é útil em processadores que possuem amplos registros SIMD, que podem passar 16 bytes por vez ou mais. Isso permitiria que você passe (por exemplo) um vetor 4 dimensional (quatro carros alegóricos) em um registro. Sistema da AMD V é um exemplo de um X86 ABI que permite isso.

Um exemplo diferente é o atributo D64_ABI do GCC, que diz a um PowerPC para passar uma estrutura nos registros sempre que possível, e não na pilha. (Isso faz parte do Darwin Abi).

typedef struct {
    int          a;
    float        f;
    char         c;
} __attribute__ ((d64_abi)) Thingy;

Thingy foo( Thingy t );

No caso acima, uma chamada para Foo passaria a coisa em um registro de flutuação e dois registros int, em vez de escrevê -lo na pilha e lê -lo de volta novamente. O valor de retorno volta aos registros da mesma maneira.

Nunca vi um compilador que faça isso automaticamente, sem que você diga, mas é possível que exista.

Outras dicas

Isto é definido no application binary interface (ABI) de seu ambiente de execução.A norma não diz nada sobre registradores do processador quando uma função é chamada, por isso é legal para criar um ambiente onde as pequenas estruturas são embalados em um único processador registrar.

Para a referência parte, eles são muito propensos a ser passado como ponteiros de qualquer maneira, desde quando dentro da função chamada o endereço de uma referência é tomada, ele deve ser resolvido para o endereço do objeto referenciado.

Em certas arquiteturas (como i386, eu sei que é antigo, mas é com isso que eu cresci;) certamente faz sentido passar em um registro, já que empurrar e sair da pilha leva muito mais (digamos entre 3-6 vezes mais) ciclos de CPU como passagem por registro. Portanto, um compilador faria um bom trabalho otimizando para isso.

Eu posso imaginar que existem outras arquiteturas onde isso não importa. Ou se os registros estiverem em uso para outras otimizações que produzem mais melhorias, não faz sentido usá -los para isso.

Que arquitetura você está usando/segmentação ou está perguntando em geral?

Eu acho que há compiladores que passarão em vagens nos registros, mesmo que sejam structs.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top