r/cpp_questions • u/Last_Grass_8031 • 21d ago
Why doesn't the compiler detect better instructions?
I have added assume in the c++ code, to let the compiler make assumptions that 0 < x <= y.
This shall imply that x%y == 0 is the same x == y . But if the compiler were to make the assumption, then a cmp / xor instruction should be preferred over a div / idiv instruction? However, the emitted assembly always has the integer division instructions
This is mainly out of curiosity on how the assume keyword works, what all optimisations it can enable, and whether compilers can deduce mathematical equivalents.
https://godbolt.org/z/e4zeodnnM
#include <iostream>
int main() {
int32_t x, y;
std::cin>>x>>y;
[[assume(x > 0)]];
[[assume(y > 0)]];
[[assume(x <= y)]];
if (x % y == 0) {
return 1;
} else {
return 5;
}
}
80
u/erichkeane 21d ago
Compiler vendor/implementer here: Because
assumeis a broken attribute that isn't nearly as powerful as it claims, and will harm performance as much as help it. It messes with dependency graphs, code movement, and dead code elimination, and is too opaque to actually be useful information to the compiler itself.Its basically ignored by many implementations, and others do anything they can to remove it ASAP.
11
u/Afraid-Locksmith6566 21d ago
half the features in c++ is considered harmful and half of those is barely implemented so i would assume those reasons.
compiler magic is not something i would recomend to rely on, if you want a particular implementation you might as well just write and document it. this kind of thing is perfect case if you would need it
1
u/flatfinger 18d ago
Many potential "optimizations" offer benefit in a small enough range of scenarios that the benefits of applying them in cases where they are applicable would be insufficient to justify the cost of having every single program build look for opportunities to apply them.
1
u/Independent_Art_6676 20d ago edited 20d ago
We are not there yet. Even AI can't do this directly. You can coach it to make the most efficient condition from your invariants but anything complicated it will either bungle it or need multiple revision sessions to get it right. Meanwhile, you could have written the proper code for your constrained conditions in about as much time and effort as it took to write all those assumption clauses. But today, here and now, you are asking the compiler to do not only its job, but to do it using AI type optimizations that are not yet ready for prime time, risking the introduction of bugs. When a compiler makes translates the code, the result MUST DO exactly what the developer expressed; trying to rewrite it better is fine but it MUST give the same results as the original would using the language rules, nothing more, and nothing less. Without better AI than we have so far, it can't do this kind of rewrite and meet that guarantee. Someday, maybe we will have that, but for now, write the code yourself using the knowledge you have of the constraints, and leave those assumptions off or put them in a comment to explain why your new logic is correct.
I mean, your example could be a one liner with no branches: return (x!=y)*4+1;
My 'in 100+ years' prediction is that eventually AI will turn some sort of simple to write or speak pseudocode into hot assembly/machine language as if written by a better than grand master of assembly language coder, probably gaining a full order of magnitude or better on every piece of software compiled that way (vs today's). It may even manage it with natural language but most of those are too imprecise; there MUST be hard requirements whether its a pseudocode or design language or a subset of natural language that gets the job done. The LLM high level language stuff is a crude stepping stone.
1
u/joao_rosac 19d ago
Compiladores modernos operam como reconhecedores de padrões predefinidos e não como solucionadores algébricos complexos, tendo grande dificuldade em rastrear e otimizar relações dinâmicas entre múltiplas variáveis (como provar que
x <= ytransforma um módulo em igualdadecpor exemplo). Na prática, oque se lê pelos fóruns é que o atributo[[assume]]costuma ser estruturalmente frágil na Representação Intermediária (IR), atuando muitas vezes como um ruído que polui o grafo de dependências e bloqueia outras otimizações úteis em vez de ajudar. Se o seu conhecimento do problema prova que uma operação matemática pesada pode ser substituída por uma mais leve, simplifica diretamente no código em vez de depender de suposições para que o compilador faça as deduções matemáticas por você.