take this code snippet
void thing(signed short ss);
void test(int i){
thing((signed short)i);
}
both gcc and clang generate
movswl %di, %edi
jmp thing(int)
however I know that the argument is between -32768 and 32767. And I can't change any of the argument types. So that movswl is basically a nop. In fact, gcc does a truncation every time it recieves a short argument. So it actually truncates it twice per in some function calls.
ideally I'd want a sort of assert_within_bounds_cast function that's sort of a cross between reinterpret_cast and bit_cast that basically says "don't worry about truncating, just use whatever register size is most convenient". I tried building it myself using __builtin_unreachable() and reinterpret_cast but it didn't work consistently and sometimes made things worse.
If you can't change the argument types to
test, you're stuck - callers can't possibly know that your function expectssigned shortwhen it accepts anint(which might be wider, but not always), and callers of the function may pass it anintoutside of your controlIs it possible you can overload the function?
Finally, watch out when analyzing the results of really trivial / non-representative cases - if you really have
voidfunctions without a mutable arg, they may be completely dropped when (further) optimizations are applied, so you can't easily have a case where both full optimizations run (which may discover and fix your case) and the function(s) exist at all!