Re: [cc65] Optimizing C code

Date view Thread view Subject view

From: Ullrich von Bassewitz (uz_at_musoftware.de)
Date: 2003-09-04 18:04:37


On Thu, Sep 04, 2003 at 08:37:31AM -0700, Shawn Jefferson wrote:
> This doesn't work (as far as I can tell), since my bit pattern in creg may
> be 01, 10, or 11.  That's why I turn off the pixel to be painted and then
> repaint it after.  Or am I missing something here?

Your original code was:

  if (creg != BAKCOL(bmp->mode)) {              // not background color?
    creg++;                                     // creg 0->01, 1->10, 2->11
    mask = creg << plot4cshift[bit];
    data |= mask;
  }

with mask and creg not being used anywhere else. So at first, you can remove
the increment of creg, because the value is not used later on:

  if (creg != BAKCOL(bmp->mode)) {              // not background color?
    mask = (creg+1) << plot4cshift[bit];
    data |= mask;
  }

And next, drop mask:

  if (creg != BAKCOL(bmp->mode)) {              // not background color?
    data |= (creg+1) << plot4cshift[bit];
  }

I would even say this is easier to understand than the old code.

> >  5. In fact, it is also possible to remove the data variable.
>
> See above.

What's the problem?

  if (creg != BAKCOL(bmp->mode)) {              // not background color?
      bmp->dat[index] = (bmp->dat[index] & ~plot4cmask[bit]) |
                        (creg+1) << plot4cshift[bit];
  } else {
      bmp->dat[index] = (bmp->dat[index] & ~plot4cmask[bit]);
  }

This will generate larger code, but on each code path, the array is addressed
two times as before. I'm not sure if this will actually generate faster code,
you will have to look at the assembly to find out.

> The x and y values are signed ints because I copied this function from the
> one that does clipping, and then removed all the clipping code.  I will make
> them unsigned, since out of bounds values with this function don't make sense.

Making them unsigned will allow the compiler to generate AND and ASR
instructions for the calculation of byte and bit, instead of using subroutines
that handle the sign extension correctly. Not using subroutines does also mean
that the code is visible to the optimizer.

> As for the pre-increment, I have never really understood how or why you would
> use it, and in all examples of C code I have seen, the post-increment operator
> is used.  Old habits are hard to break.  I'll try that in the code as well.

post-increment allows to use the old value of the variable. Since cc65 is too
dumb to determine if the programmer will actually use the value later, it
generates code taking this possibility into account. The result is something
like

        get old value into register
        save it somewhere
        increment value in register
        store value back
        reload old value  (<-- removed by the optimizer of not needed)

With pre-increment, the old value of the variable is no longer needed, so the
generated code is something like

        increment variable
        load variable     (<-- removed by the optimizer of not needed)

It is a good habit of using ++var instead of var++ if you don't plan to use
the old value later, since when switching to C++, one can overload the ++
operator and use it with objects. In this case, the difference between pre-
and post-increment is much larger (often malloc is involved when using
post-increment with objects), and even better compilers are no longer able to
optimize the code in question, because the ++ operator may be a function call.

Regards


        Uz


-- 
Ullrich von Bassewitz                                  uz_at_musoftware.de
----------------------------------------------------------------------
To unsubscribe from the list send mail to majordomo_at_musoftware.de with
the string "unsubscribe cc65" in the body(!) of the mail.


Date view Thread view Subject view

This archive was generated by hypermail 2.1.3 : 2003-09-04 18:04:48 CEST