C++ contra Assembly: por que o compilador supera o código manual

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Introdução: Por que o computador "pensa" mais rápido que o programador?

\n\n

Imagine: você passou a noite escrevendo no papel a sequência de Collatz para o número 27. E então seu colega escreveu um loop em C++ que, em um segundo, processou um bilhão de números. Você está furioso? Espere, isso é só o começo.

\n\n

Em 2025, no Stack Overflow, uma pergunta antiga, mas muito reveladora, explodiu com nova força: "Why does C++ code for testing the Collatz conjecture run faster than hand-written assembly?". À primeira vista, Assembly é um diálogo puro com o processador, sem intermediários. Como é possível que um C++ de alto nível supere o Assembly escrito por um humano?

\n\n

Vamos analisar esse paradoxo usando o exemplo da hipótese de Collatz (também conhecida como problema 3n+1). Você descobrirá por que os compiladores C++ modernos são verdadeiras máquinas do tempo e como, em 2025, escrever código que será mais rápido do que o "controle manual" dos registradores.

\n\n

O que é a hipótese de Collatz e o que o C++ tem a ver com isso?

\n\n

Vamos relembrar a essência: pegue qualquer número natural n. Se for par — divida por 2. Se for ímpar — multiplique por 3 e some 1. A hipótese afirma que qualquer número, mais cedo ou mais tarde, chegará a 1. A tarefa do programador é verificar isso para a maior faixa de números possível.

\n\n

A implementação clássica em C++ é assim:

\n\n
#include <iostream>\n\nint collatz_steps(long long n) {\n    int steps = 0;\n    while (n != 1) {\n        if (n % 2 == 0) {\n            n /= 2;\n        } else {\n            n = 3 * n + 1;\n        }\n        ++steps;\n    }\n    return steps;\n}\n\nint main() {\n    long long max_steps = 0;\n    long long best_num = 0;\n    for (long long i = 1; i <= 1000000; ++i) {\n        int s = collatz_steps(i);\n        if (s > max_steps) {\n            max_steps = s;\n            best_num = i;\n        }\n    }\n    std::cout << "Número: " << best_num << " passos: " << max_steps;\n}\n
\n\n

Parece simples. Mas foi esse código simples que gerou a lendária disputa com o Assembly.

\n\n

Por que o Assembly perde? Principais erros de 2025

\n\n

Quando um desenvolvedor escreve em Assembly, ele frequentemente pensa: "Eu sei como o processador funciona, vou escrever perfeitamente". Mas os processadores modernos não são apenas executores de instruções. Eles são pipelines superescalares complexos com previsão de desvios, execução especulativa e memória cache. O compilador C++ (GCC, Clang, MSVC) conhece tudo sobre sua arquitetura alvo.

\n\n

Erro nº1: Ignorar a otimização de desvios

\n\n

No Assembly manual, o programador frequentemente escreve desvios "diretos":

\n
; Pseudo-Assembly\ncheck_even:\n    test rax, 1\n    jnz is_odd\n    shr rax, 1\n    jmp next\nis_odd:\n    mov rbx, rax\n    shl rax, 1\n    add rax, rbx\n    inc rax\nnext:\n    ...
\n\n

O compilador C++ com a flag -O3 faz de forma mais inteligente. Ele usa CMOV (conditional move) e mágica de bits. Em vez de desvios, usa aritmética:

\n\n
; GCC 14 gerará algo como:\n    mov     rcx, rax\n    shr     rcx, 1          ; divide por 2 (se par)\n    and     eax, 1          ; verifica o bit menos significativo\n    lea     rdx, [rax + rcx*2 + 1] ; cálculo esperto para ímpar\n    test    eax, eax\n    cmove   rax, rcx        ; se par - pega a divisão\n    cmovne  rax, rdx        ; se ímpar - pega 3n+1\n
\n\n

Resultado: sem stalls no pipeline devido a desvios previstos incorretamente. Em 2025, isso é crítico, pois o preditor de desvios na CPU ficou mais inteligente, mas ainda não é ideal para números aleatórios.

\n\n

Erro nº2: Esquecer a vetorização (AVX-512)

\n\n

Os compiladores C++ modernos (especialmente Clang 18+ e GCC 14+) vetorizam loops automaticamente. Se você escrever um loop de verificação simples, o compilador pode processar 8 números por ciclo, usan

Blogs

Book Recommendations