Saturday, July 14, 2012

I was looking for another instance where int-to-char conversion was done incorrectly. Once again, GCC was assuming that byte quantities stored in registers are stored in the least significant byte. After much poking around, I found the problem in find_reloads. It was in a portion of code which was a default handler of reload conditions.

I had earlier fixed code in this function which handled most cases of subreg substitution, but I believe since the source and destination registers were the same in this case, execution skipped down to the default handler.

In any case, I added a check on that path to prevent modification of the subreg expression when int-to-char and char-to-int converstons are called for. These cases are properly handled in the machine description, and the correct instructions are issued as expected.

Unfortunately, once find_reloads was fixed, there was still a problem. The instruction was being broken in a different way, and looked something like this:

(insn 72 71 74 3 lucien2_8.c:39 (set (reg:QI 7 r7 [orig:73 D.1232 ] [73])
        (reg:QI 7 r7 [+1 ])) 71 {movqi} (nil))

This effectively returns us to the situation we just fixed, that the byte quantity was assumed to be in the least significant byte of a register.

After tracing execution and checking the evolution of the instruction, I found where the subreg expression was converted to the "+1" form above. This was done in alter_subreg.

The code there was intended to handle special cases which escaped processing by simplify_subreg. Since I've disabled a lot of sode which would remove subreg expressions, these default handlers are getting more use.

At this point, I need to go through my earlier notes, but I think it's time for another release.

No comments:

Post a Comment