Академический Документы
Профессиональный Документы
Культура Документы
1. Introdução
A SSA, ou Static Single Assignment, é uma das inúmeras técnicas de otimização que
podem ser aplicadas e implementadas em um compilador.
É uma técnica independente de linguagem e processadores (arquitetura), pois ela
é aplicada em uma representação intermediária da compilação. Logo após a aplicação
da SSA, e as otimizações que se beneficiam dela, é necessário ”desfazer” a SSA para o
código ser representado adequadamente no hardware.
Ela foi concebida na década de 80 nos laboratório de pesquisa da IBM, com a
finalidade de simplificar o fluxo de controle e tornar mais fácil a adoção de técnicas que
são beneficiadas pela declaração única de uma variável.
Antigamente algumas otimizações neste sentido eram feitas utilizando uma
técnica chamada def-use chain, que é uma eficiente estrutura de dados que contém o
campo de uso de cada variável e para cada declaração o compilador mantém os ponteiros
da variável, segundo Appel (1998), mantendo assim cada definição das variáveis aos usos
que cada uma alcança.
2. Definição
Neste conceito de otimização, cada variável, que pode ser chamada de ”pseudo-
registrador”, é atribuı́da apenas uma única vez, e cada uso da variável é dominado pela
definição dela. Isto viabiliza uma análise mais rápida do código, tornando mais eficiente
e fácil aplicar outras otimizações. Com a SSA é mais fácil criar um grafo de fluxo de
controle, ou controle de dependencia, e até mesmo uma análise de data-flow.
Com a simplificação realizada pelo formato SSA, apenas uma única definição
pode alcançar um uso particular da variável, assim, achar a tal definição é trivial. Ela
também permite algoritmos, insensı́veis ao fluxo, gozar dos benefı́cios de algoritmos
sensı́veis ao fluxo, sem o custo de análises de fluxo de dados.
Esta técnica foi originalmente desenvolvida por Ron Cytron, Jeanne Ferrante,
Barry Rosen, Mark Wegman, and Ken Zadeck. Eles eram pesquisadores da IBM na
década de 80.
3. Detalhes
Um simples exemplo de atribuições pode ilustrar o ganho que há na análise de um código
com SSA, como no algoritmo a seguir:
A = 1;
A = 2;
B = A;
A1 = 1;
A2 = 2;
B1 = A2 ;
4. Os Algoritmos
Mayers (2003, p. 3) define SSA como um conceito que explicita o fluxo de informações
de dados de um determinado programa, concentrando na maneira como é realizada a
definição (ou seja, atribuição) e uso de variáveis.
Briggs (p. 1) apresenta que a SSA é uma representação intermediária que os com-
piladores utilizam para facilitar a análise do aplicativo e beneficia as otimizações. Appel
(1998, p. 443) expõe que muitas análises de dataflow precisam encontrar as dominan-
cias de cada definição de variável, e que para isto existe o def-use chain. Mas este autor
apresenta a SSA como uma melhoria desta ideia, definindo-a como ”uma representação
intermediária na qual cada variável tem apenas uma definição no texto do programa”.
O autor Mayers (2003) ressalta que há complicações evidentes quando há fluxos
de controles (tomadas de decisões com if, laços com um for, etc.). A Figura 1 demonstra
o fluxo de controle do algoritmo proposto.
Logo, deve ocorrer a definição de uma estratégia para portar a aplicação para a
forma SSA.
Segundo o autor (MAYER, 2003), há dois passos fundamentais para a adoção da
SSA.
O primeiro passo fundamental que Mayers apresenta é uma declaração especial,
chamada de φ-function. Esta função, que será tratada com mais detalhes neste artigo,
basicamente cuidará dos nós propostos no algoritmo, representando as possibilidades, do
uso de uma variável numerada, perante uma bifurcação.
O segundo é a re-nomeação das variáveis de acordo com sua dominância.
Ambos os passos citados podem ser vistos na Figura 2.
Foi levantada então uma fase inicial, a identificação das necessidades das φ-
function, e suas aplicações. A Figura 3 demonstra outro algoritmo passando pelas três
fases.
Com isto, é preciso propor soluções práticas para que algoritmos sejam aplica-
dos aos códigos para portá-los para o SSA. Mayers (2003) apresenta algumas questões,
melhorando-as, além de propor dois algoritmos para as mesmas.
Mayers (2003), ressalta também que há métodos e técnicas especı́ficas para lidar
facilmente com arrays e records e Appel extende isto até os ponteiros.
Figure 2. Renomeação de variáveis
Uma atribuição de um array para outro, por exemplo, pode ser tratada com uma atribuição
entre variáveis escalares. No entanto, as atribuições dos arrays, muitas vezes tomam a
forma de atribuições de um elemento da matriz. Mas, mesmo neste caso, a idéia é usar a
matriz (array) como uma variável escalar. Para realizar as operações em arrays, Mayes
(2003) ilustra métodos como: Acesso (Access) e Atualizar (Update) - veja a Figura 4:
A fim de ajustar as estruturas records para o a forma SSA, podemos aplicar a mesma
técnica, citada para os arrays, considerando o registro como uma matriz e os campos de
registro como elementos da matriz.
Figure 4. Manipulação de Arrays
M[i] = 4;
x = M[j];
M[k] = j;
Não há como tratar cada posição da memória individualmente, como uma variável
separada, porque não ha como saber se i, j, e k é o mesmo endereço.
Mas é possı́vel tratar a memória como uma ”variável”, onde a instrução load cria
um novo valor (da memória inteira), acompanhe o racı́ocı́nio no código a seguir:
M1 = store(M0 , i, 4);
x = load(M1 , j);
M2 = store(M1 , k, j);
M1 = store(M0 , i, 4);
M2 = store(M1 , k, j);
x = load(M1 , j);
Appel (1998) propôs esta solução que acaba, como Mayers, cobrindo de maneira
semelhante, tendo a única alteração no nome dos métodos, ou funções, que tratam a
leitura e atribuição de valores em estruturas como matrizes e outras estruturas mantidas
em memória, como ponteiros.
Repare que não há como chegar nos nós circulados, sem antes passar pelo nó
denominado ”5”, os nós dentro da fronteira do nó ”5”, por sua vez, estabeleciriam suas
próprias fronteiras de dominância, evitando assim que o nó ”5” englobe todos os nós.
Para tal técninca evoluir dentro da SSA, é preciso determinar a árvore de
dominância, que pode ser construı́da com propriedades do fluxo de controle correspon-
dente.
Os nós da árvore e do fluxo de controle são idênticos, segundo Mayers (2003), e
as bordas da árvore são determinadas usando a propriedade de dominância imediata do
fluxo de controle como é demonstrado na Figura 6.
É um algoritmo de duas fases, que se baseia na simples idéia: primeiro devem ser
inseridas as φ-funcions quando possı́vel. Em seguida, iterativamente, excluir aquelas que
não são necessárias.
A primeira fase do algoritmo é chamada de RC, onde serão distribuı́das as funções
φ livremente. A segunda é a fase de minimização das funções φ, ou seja, é feita uma limpa
das funções, tentanto otimizar as chamadas da mesma, como pode ser visto na Figura 9.
O autor (Mayer, 2003) complementa que Aycock and Horspool propõe
otimizações neste algoritmo, como: One-pass RC phase, Mapping table. Basic blocks
with single predecessors.
Mayers (2003) conclui que os algoritmos para SSA propostos por Cytron, Ay-
cock e Horspool são eficientes e que o SSA se tornou uma técnica padrão, amplamente
utilizada, relembrando, inclusive, sua implementação no compilador GNU, o GCC.
assumiu.
Para suprir esta necessidade é que foi introduzida a função φ. Segundo Appel
(1998, p. 434-435) ela expõe as variáveis resultantes do nó.
Appel (1998) propõe uma solução para conversão de um programa para a forma
SSA muito próxima a Geração Simples de SSA citada por Mayers (2003), na qual
primeiramente deve-se adicionar as φ-functions e, em seguida, re-nomear as variáveis.
O autor Briggs propõe uma alternativa para as φ-funcions.Trata-se das ”Cópias” (Copies).
Briggs propõe isto baseando-se na idéia de que raramente algum computador tenha um
hardware capaz de representar e executar as φ-funcions.Com isto os compiladores já
acabam fazendo a cópia naturalmente. Porém é possı́vel refiná-la com a Coloração de
Grafos do Fluxo de controle.
Briggs ressalta que a Coloração de Grafos, não é uma tarefa trivial, mas se não for
executada adequadamente o compilador pode executar o ”copy folding” ingenuamente,
levando a erros.
Briggs monta o algoritmo da Figura 10 para escalonar o suo das Cópias, definidas
pelo mesmo.
7. O Uso e Aplicação da SSA
Como já mencionado no artigo, a forma SSA é utilizada para a otimização do programa
em um compilador. Segundo Mayers (2003) as seguintes otimizações podem se beneficiar
de SSA Form.
9. Curiosidades
O compilador GCC, a partir da sua versão 4.0 (Julho de 2005) introduziu em suas
otimizações a SSA. Antes, a representação intermediária gerada por ele era chamada de
RTL (Register Transfer Language).
10. Crı́tica
Os autores, já citados, em momento algum apresentaram um histórico mais preciso da
técnica SSA. A conseqüência é a falta de clareza na hora de ressaltar os reais benefı́cios
da técnica diretamente ligada ao produto final da compilação. Assim ficou apenas demon-
strado que a técnica beneficia outros algoritmos de otimização de código, pois a SSA
simplifica a analise de fluxo de controle do código, evidenciando o tempo de vida das
variáveis. Isto fez com que a SSA adquirisse uma classificação de técnica auxiliar.
A SSA é uma técnica que tem que ser aplicada, e spos os processamento de
código pertinentes, deve-se ”retirá-la de cena”. Isto acaba comprometendo o tempo de
compilação. Assim, algumas plataformas, que próvem uma recompilação de código, após
uma análise do comportamento da aplicação, para melhorar o desempenho de algumas
rotinas, acabam não se beneficiando tanto desta técninca, pois o tempo de compilação
acaba embutido no tempo de execução .
Os autores poderiam ter deixado claro se a SSA sozinho traz algum benefı́cio ao
produto final do compilador.
Além disto, pela falta de precisão do histórico, não ficou claro qual foi o real
motivo que impulsionou os pesquisadores da IBM a desenvolver algo desta natureza.
Os autores também ficaram devendo mais exemplos da evolução de um código
normal para um otimizado, passando pela SSA. Além disto poderiam ter traçado exemplos
colocando lado a lado a SSA e o use-def Chain.
12. Conclusão
A SSA é um conceito que simplifica a adoção de outras técnicas de otimização. Estas por
sua vez, implicam diretamente na otimização de códigos e na aplicação final, melhorando-
a em vários sentidos, como: tamanho final da aplicação, performance, melhor uso de
hardware etc.
Foi ressaltado que a SSA é uma técnica onde deve ocorrer um retorno para uma
representação simples do código, devido a falta de suporte (de hardware) para algumas
caracterı́sticas da forma SSA, como as φ-funcions.
Ficou claro também que um dos alicerces principais, da técninca SSA, está nas
φ-funcions, que garantem o suo correto de variáveis nas bifurcações do código.
O Artigo apresentou algumas das técnicas que se beneficiam da SSA, explicando
seus conceitos e ilustrando a evoluçã, partindo da conversão para a SSA até chegar na
otimização, como foi o casa do Code Motion.
Para tal, houve crı́ticas a autores citados no artigo por ignorarem as origens da
técnica e comprometer uma aplicação moderna da técnica, devido ao déficit da proposta
inicial da SSA.
Logo foi proposto um novo estudo, onde seriam analisados dados provenientes da
aplicação da SSA nos compiladores de plataformas como o JAVA e o C#, estudando o
comportamento do código e desempenho da aplicação, quando a técnica for aplicada na
geração de byetecode, por exemplo.
References
APPEL, Andrew W. (1998). Moder Compiler Implementation in C. England: Cambridge
University.
BRIGGS, Preston et. Al. (s\d) Practical Improvements to the Construction and Destruc-
tion of Static Single Assignment Form. Tera Computer Company.
CYTRON, R. et. Al. (1989) Efficiently computing static single assignment form and the
control dependence graph. ACM Trans.
GCC. Seção GNU Compiler Collection. Disponı́vel em: <http://gcc.gnu.org/>. Acesso
em: 5 nov. 2009 às 9h10.
Seção Conhecendo o GCC 4, 28 out. 2008. <http://www.ibm.com/developerworks/br/library/l-
gcc4/index.html>. Acesso em: 05 nov. 2009 às 8h.
MAYER, Sabine. (2003). Static Single-Assignment Form and Two Algorithms for its
Generation. University of Konstanz.
WIKIPEDIA. Seção Static Single Assignment Form. Disponı́vel em:
<http://en.wikipedia.org/wiki/Static single assignment form>. Acesso em: 5
nov. 2009 às 9h.
Figure 10. Algoritmo para escalonamento de inserção de cópias
Figure 11. Propagação de Constante