The div function and its kin were originally introduced in C89 for portability and efficiency. The portability argument has mostly gone by the wayside in C99 when the semantics of division and modulo were tightened up; as compilers have become better at optimizing integer division the efficiency argument for this API has become weaker as well. Nevertheless, the functions are still in the standards and being used, albeit not very often. This change adds basic support for folding calls to these functions with constant arguments. It assumes that struct div members are laid out in the order they're described. The standards don't require this but I don't know of any systems where the assumption doesn't hold. If there's a concern with this assumption then the code could be made conditional based on the result of a configury test.
This simplistic solutions leaves room for improvements, such as:
- Fold div(X, 1) to {X, 0} for any X (and possibly also div(X, -1) to {-X, 0}).
- Fold div(X, Y).quot to X / Y and div(X, Y).rem to X % Y for any X and Y when only one of the struct members is used.
I would have wanted to implement (1) in the initial patch, mostly as a learning exercise, but couldn't find a simple way to create an initializer for a nonconstant struct like there is for a constant one with ConstantStruct::get(). Any suggestions?
(2) seems outside the scope of this initial solution but it too looks like an interesting learning opportunity, so I'd welcome pointers here as well.
Any reason why this one branch checks bitwidth >= 16, but we accept any for the others?