See the problem on godbolt. In this code:
define i64 @fast(i8* align 1) unnamed_addr #0 {
%2 = load i8, i8* %0, align 1
%3 = sub nuw i8 %2, 10
%4 = zext i8 %3 to i64
ret i64 %4
}
running through opt causes the sub to be switched out for
Note that the nuw flag was lost. This causes the compiled assembly to include an extra instruction. Originally found in rust-lang/rust#91449 .
Alive2 actually indicates that the nuw flag would be incorrect here, which makes sense since -10 is secretly just 246. Is there another way to address this? I can close this issue if the only reasonable response is "yeah, canonicalization requires us to do this, and sometimes that causes problems. Sorry"