4 pontos por GN⁺ 2026-01-13 | 1 comentários | Compartilhar no WhatsApp
  • Analisa por vários ângulos as limitações estruturais e a dívida técnica do projeto LLVM, apontando de forma concreta as áreas que precisam de melhorias
  • Apresenta gargalos na operação de um grande projeto open source, como falta de revisão, instabilidade de API, tempo de build e compilação e instabilidade de CI
  • Entre os problemas de design do IR, inclui tratamento de valores undef, codificação de restrições, semântica de ponto flutuante e incompletude da especificação
  • Aponta problemas estruturais de longo prazo, como heterogeneidade dos backends, confusão no tratamento de ABI e atraso na transição para o GlobalISel e o gerenciador de passes
  • Em vez de negar o estado atual do LLVM, apresenta isso como uma oportunidade para melhoria contínua e ampliação das contribuições

Principais problemas estruturais

  • A falta de capacidade de revisão é apontada como o maior gargalo

    • Há muitos autores de código, mas poucos revisores, o que leva à fusão de mudanças não suficientemente validadas
    • Como a solicitação de revisão é responsabilidade do autor, novos contribuidores têm dificuldade para encontrar revisores adequados
    • A adoção do sistema automático de atribuição de PRs do Rust é citada como possível melhoria
  • Mudanças frequentes (churn) na API e no IR sobrecarregam os usuários

    • A API em C é relativamente estável, mas a API em C++ muda com frequência, aumentando o custo de manutenção de frontends e backends
    • A filosofia “Upstream or GTFO” faz com que código não compartilhado não seja considerado nas decisões
  • Problema de tempo de build excessivo

    • O LLVM é composto por mais de 2,5 milhões de linhas de código C++, e o build leva muito tempo; em builds de depuração, o uso de memória e disco cresce fortemente
    • Cabeçalhos pré-compilados (PCH), build padrão com dylib e daemonização de testes são discutidos como formas de melhoria
  • Instabilidade de CI

    • Mais de 200 buildbots testam em vários ambientes, mas nem sempre conseguem manter um “estado verde”
    • Testes flaky e problemas nos buildbots diluem os sinais de alerta, dificultando a detecção de erros reais
    • A introdução de testes prévios para PRs trouxe alguma melhora, mas ainda não resolveu o problema de forma estrutural
  • Falta de testes end-to-end

    • Os testes unitários de otimizações individuais são sólidos, mas quase não há testes cobrindo o pipeline completo ou a integração com backends
    • O llvm-test-suite existe, mas não cobre de forma suficiente combinações básicas de operações e tipos de dados

Problemas relacionados a backend e desempenho

  • Heterogeneidade entre backends

    • As etapas intermediárias são unificadas, mas os backends têm muitas modificações independentes por alvo, o que aumenta a duplicação e a divergência
    • Há uma tendência de adicionar hooks específicos por alvo em vez de investir em otimizações comuns
  • Tempo de compilação

    • É lento em JIT e em linguagens que geram grandes volumes de IR, como Rust e C++
    • Builds com -O0 são particularmente lentos, e o backend TPDE é apresentado como uma alternativa até 10 a 20 vezes mais rápida
  • Ausência de rastreamento de desempenho

    • Não existe uma infraestrutura oficial de acompanhamento de desempenho em runtime
    • O sistema LNT tem instabilidade de funcionamento, problemas de UX e falta de dados, o que reduz bastante sua eficácia

Problemas de design do IR

  • Complexidade no tratamento de valores undef

    • Eles podem assumir valores diferentes a cada uso, o que provoca erros durante otimizações
    • No futuro, podem ser substituídos por valores poison, mas o tratamento de poison em memória ainda é insuficiente
  • Incompletude e inconsistência da especificação

    • Existem casos antigos de mau funcionamento que seguem sem solução
    • Há desafios de design, como o modelo de provenance
    • Para resolver isso, foi formado um grupo de trabalho de especificação formal
  • Falta de consistência na codificação de restrições

    • Flags de poison, metadados, atributos, assumes e outros métodos se misturam
    • A perda de informação ou sua retenção excessiva impacta negativamente as otimizações
  • Problemas na semântica de ponto flutuante (FP)

    • Ocorrem inconsistências com NaN sinalizador, ambientes não padronizados, tratamento de denormais e precisão extra do x87
    • Isso é tratado separadamente por intrinsics de FP com restrições, o que aumenta a complexidade

Outros problemas técnicos

  • Atraso em migrações parciais

    • O novo gerenciador de passes foi aplicado apenas à etapa intermediária; os backends ainda usam o modelo antigo
    • O GlobalISel ainda não conseguiu uma transição completa após 10 anos, coexistindo com o SDAG
  • Confusão no tratamento de ABI e convenções de chamada

    • A divisão de responsabilidades entre frontend e backend é pouco clara e mal documentada
    • A introdução de uma biblioteca de ABI e implementações protótipo estão em andamento
    • Há casos em que a ABI muda conforme a ativação de recursos do alvo
  • Inconsistência na gestão de funções built-in e libcalls

    • TargetLibraryInfo e RuntimeLibcalls são separados, o que prejudica a consistência
    • Não há como reconhecer a disponibilidade conforme o tipo de biblioteca de runtime (libgcc, compiler-rt etc.)
    • Falta um ponto de customização para runtimes externos, como o Rust
  • Ineficiência da estrutura Context / Module

    • Tipos e constantes ficam no Context, enquanto funções e globais ficam no Module
    • A impossibilidade de acessar o layout de dados dificulta tarefas como constant folding
    • Não é possível fazer link entre contextos diferentes, e a estrutura precisa ser simplificada
  • Pressão de registradores causada por LICM (loop-invariant code motion)

    • O hoist é feito sem modelo de custo
    • O backend não faz sink novamente, o que aumenta spill e reload

Conclusão

  • Os problemas listados são desafios estruturais decorrentes da maturidade e da escala do LLVM e são apresentados como uma oportunidade para melhorar a qualidade do projeto e a experiência dos contribuidores
  • Em algumas áreas, como otimização de build, biblioteca de ABI e rastreamento de desempenho, o trabalho de melhoria já está em andamento
  • No geral, o LLVM continua muito poderoso, mas refatoração contínua e organização da especificação são essenciais

1 comentários

 
GN⁺ 2026-01-13
Comentários do Hacker News
  • O texto todo está bem organizado, então concordei bastante com muita coisa.
    Hoje em dia, a estabilidade do LLVM IR está bem alta. Rebaseei o Fil-C do LLVM 17 para o 20 em um único dia.
    Em outros projetos também mantive o mesmo pass em várias versões do LLVM sem grandes problemas.
    Ainda assim, a pressão de registradores no LICM é especialmente séria em fontes que não são C/C++. O problema parece ser menos o LICM em si e mais o fato de o regalloc precisar aprender melhor a rematerialize

    • O regalloc já conhece rematerialize. Só que, como o backend tem uma visão local em comparação com o otimizador, fica difícil desfazer decisões ruins tomadas pelo LICM
    • O pass de rematerialize já existe. Não há necessidade de acoplá-lo ao register allocation. O regalloc do LLVM também nunca foi perfeito.
      Seria bom abrir mais opções para que desenvolvedores de frontend possam benchmarkar várias configurações e escolher o melhor valor
    • Não sou especialista em LLVM, mas quando mexi com isso no passado, o IR me pareceu mais um vocabulário comum entre várias linguagens do que uma linguagem única.
      Como cada ferramenta e componente tem suas próprias regras, diferenças entre versões parecem até naturais. Fico me perguntando se entendi isso errado
  • Tentei pedir ao responsável por compiler-rt para mudar um único boolean para conseguir compilar o LLVM 18 no macOS, mas a issue foi trancada como “heated” e continua sem solução há 4 anos.
    Mesmo assim, ainda amo o LLVM. clang-tidy, ASAN, UBSAN, LSAN, MSAN, TSAN são realmente excelentes.
    Acho que escrever código C/C++ sem usar clang-tidy é uma escolha errada.
    Só que -fbounds-safety existe apenas no AppleClang, e MSAN/LSAN só existem no LLVM Clang. O Xcode também não inclui clang-tidy, clang-format nem llvm-symbolizer.
    No fim, no macOS eu tive que compilar o Darwin LLVM por conta própria para usar.
    O lado Linux também é confuso. O RHEL não fornece libcxx, mas o Fedora fornece. Porém, libcxx instrumentada para MSAN não existe em nenhuma distribuição.
    O Fedora quase chegou lá, mas ainda é preciso compilar o compiler-rt manualmente

    • Recebi a recomendação de usar Gentoo. Veja a wiki do LLVM no Gentoo
    • Também houve a pergunta se Chimera Linux ou Mandriva não fazem o LLVM funcionar bem por padrão. O Chimera é bastante nativo de LLVM
  • Ao passar por discussões recentes sobre LLVM, senti que é absolutamente necessário um test suite executável começando em LLVM IR, e não em C.
    Quando você cria um backend diretamente, faltam documentos sobre SelectionDAG e GlobalISel, e o significado das operações é ambíguo, então é fácil implementar errado

  • A API C parece algo deixado de lado dentro do LLVM. Muitas opções e passes do opt não estão expostos

    • Isso acontece porque a expressividade da API C++ do LLVM é difícil de transportar para uma interface no estilo C.
      Como a maioria dos desenvolvedores usa a API C++ diretamente, a API C acaba ficando em segundo plano e termina como uma cidadã de segunda classe
  • Como code review não leva a uma recompensa imediata, as pessoas acabam não fazendo muito isso.
    Se revisão também desse crédito de contribuição, talvez houvesse motivação.

    • Dentro da empresa também passamos por problema parecido. Minha empresa inclui a qualidade e a quantidade de reviews como critério de avaliação, mas ainda assim isso não gera motivação suficiente
  • Há 6 anos eu compilava o LLVM com frequência em um notebook Dell 9360 com 8 GB. Reduzindo o paralelismo na etapa de link, dava para ficar dentro do limite de memória.
    Fico curioso se ainda hoje dá para compilar com 8 GB.

    • Dá para fazer isso desativando builds paralelos e garantindo alguns GB de swap. Só que é preciso ajustar as flags de configuração do linker
    • Em um Mac M1, o LLVM compila em menos de uma hora em todas as configurações de build
  • No começo do LLVM, uma vantagem era a velocidade de compilação mais alta que a do GCC.
    Agora, 23 anos depois do LLVM, fico me perguntando se surgirá algo novo.

    • Recentemente houve o projeto TPDE, que tornou o backend -O0 do LLVM de 10 a 20 vezes mais rápido, mas não recebeu atenção.
      Também existem alternativas como o Cranelift, que não usa LLVM IR (Cranelift GitHub)
    • Ainda assim, o LLVM é excelente para compilar C/C++. Não é perfeito, mas alcançar um nível semelhante exige dezenas de milhares de horas-homem de esforço
  • O maior sofrimento é lidar com ABI e convenções de chamada.
    É preciso gerenciar a passagem de argumentos diretamente no frontend e, às vezes, até calcular a quantidade de registradores

  • O texto dizia que “frontends ficam protegidos graças a uma API C estável”, mas na prática não é bem assim.
    Algumas APIs são estáveis, mas partes como Orc mudam com frequência.

  • O LLVM parece quase não ter um sistema de revisão de issues. Os relatórios de bug que enviei também continuam sem tratamento há anos