Implicit Conversion Sanitizer is *almost* feature complete.
There aren't *that* much unsanitized things left,
two major ones are increment/decrement (this patch) and bit fields.
As it was discussed in PR39519,
unlike CompoundAssignOperator (which is promoted internally),
or BinaryOperator (for which we always have promotion/demotion in AST)
or parts of UnaryOperator (we have promotion/demotion but only for certain operations),
for inc/dec, clang omits promotion/demotion altogether, under as-if rule.
This is technically correct: https://rise4fun.com/Alive/zPgD
As it can be seen in InstCombineCasts.cpp canEvaluateTruncated(),
add/sub/mul/and/or/xor operators can all arbitrarily be extended or truncated:
https://github.com/llvm/llvm-project/blob/901cd3b3f62d0c700e5d2c3f97eff97d634bec5e/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp#L1320-L1334
But that has serious implications:
- Since we no longer model implicit casts, do we pessimize their AST representation and everything that uses it?
- There is no demotion, so lossy demotion sanitizer does not trigger :]
Now, i'm not going to argue about the first problem here,
but the second one needs to be addressed.
As it was stated in the report, this is done intentionally,
so changing this in all modes would be considered a penalization/regression.
Which means, the sanitization-less codegen must not be altered.
It was also suggested to not change the sanitized codegen to the one with demotion,
but i quite strongly believe that will not be the wise choice here:
- One will need to re-engineer the check that the inc/dec was lossy in terms of @llvm.{u,s}{add,sub}.with.overflow builtins
- We will still need to compute the result we would lossily demote.
- I suspect it would need to be done right here, in sanitization. Which kinda defeats the point of using @llvm.{u,s}{add,sub}.with.overflow builtins.
- OR, we would need to do that in the compiler-rt handler. Which means we'll need a whole new handler. Also doesn't really see all that worthwhile to me.
- At least X86 (but likely others) pessimizes all sub-i32 operations (due to partial register stalls), so even if we avoid promotion+demotion, the computations will likely be performed in i32 anyways.
While looking into this, i have noticed a few more LLVM middle-end missed canonicalizations,
and filed PR44100,
PR44102.
Those are not specific to inc/dec, we also have them for CompoundAssignOperator,
and it can happen for normal arithmetics, too. But if we take some other path in the patch,
it will not be applicable here, and we will have most likely played ourselves.
TLDR: front-end should emit canonical, easy-to-optimize yet un-optimized code.
It is middle-end's job to make it optimal.
I'm really hoping reviewers agree with my personal assessment of the path this patch should take..
Fixes PR44054.
modelled -> modeled