Consider the attached .ll file. Do: llvm-as foo.ll -o - | ./llvm-dif -o foo-cmp.ll I have (x86-linux): .... - %ov35 = add i32 %ov16, -29 ; <i32> [#uses=1] + %ov35 = add i32 %ov16, -93 ; <i32> [#uses=1] store i32 %ov35, i32* %state %pcc8 = add i32 %pcv7, 1 ; <i32> [#uses=1] store i32 %tmp20, i32* %tmp20_c @@ -321,7 +321,7 @@ %ov7 = xor i32 %ov18_cc, 251 ; <i32> [#uses=3] %ov41 = xor i32 %ov7, 116 ; <i32> [#uses=1] %ov63 = sub i32 139, %ov7 ; <i32> [#uses=2] - %hvar68 = add i32 %ov63, -1 ; <i32> [#uses=1] + %hvar68 = add i32 %ov63, -9 ; <i32> [#uses=1] and so on. Valgrind is quite. It's definitely an assembler bug, since output binary code is broken.
Created attachment 699 [details] failed .ll
Note, that -93 is 0xFFF...FE3 and -29 is 0xFFFF...FA3. APInt issues?
Err. Vice-versa. A3 and E3
Well. The problem is definitely APInt issue. Let's look into {NInteger} rule in the Lexer.l file. It correctly receives "-93" as yytext. But we have minBits = 6 and numBits = 7. After trunc we have "-29" as a value...
One more addition. In any of such bad cases executing getSExtValue() before trunc will result *positive* number. E.g.: +35 for "-93", "7 for "-9", +58 for "-70". Funny, eh? :)
This is definitely a bug in APInt::getMinSignedBits(). For some values it is off-by-one. I will fix this shortly.
This problem only affected negative integers whose "next to last" significant bit was set. In such cases the number of bits computed as needed by the value was off-by-one as it did not account for the sign bit. Consequently, the number was parsed correctly by the "fromString" constructor but truncated to the wrong length which changed the value. This simple patch fixes it: http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20070305/045759.html