[gnu.gcc.bug] kudos and slight deoptimization

jthomas@NMSU.EDU (04/10/89)

First, my compliments on the code gcc produces -O !!
(What do I know?  Well, I've been observing compiled code for ~20 years.  I
was the DEC F40 and Fortran-10 maintainer for a while, ...)

I would like to point to one slight deoptimization that happens in the 68k
code generation.  The following program is a chopped version of a larger
file that was my first (but definitely not last!) experiment (well, maybe
it was my only "experiment" - now I just use gcc -O always).

------------------------------ code ------------------------------

union PointCalculateFormat
  {
    struct
      {
	short int IntegerPart;
	unsigned short int FractionPart;
      } DividedValue;
    struct
      {
	int CombinedParts;
      } CombinedValue;
  };

#define PointFormatOneHalf 0x8000 /* value for 1/2 in above format */

struct XPointArray {
  short x,y;
};
extern void foo(struct XPointArray *x); /* dummy to cause code generation */

void DrawALine(FromX,		/* starting X coordinate */
	       FromY,		/* starting Y coordinate */
	       ToX,		/* ending X coordinate */
	       ToY)		/* ending Y coordinate */
     int FromX, FromY, ToX, ToY;

{
  union PointCalculateFormat CurrentX, CurrentY; /* moving X & Y positions */
  int XIncrement, YIncrement;	/* delta values between adjacent points */
				/*  (actually in PointCalculateFormat, but */
				/*   only referenced in int format for speed */
  int ConversionFactor;		/* from ToX-FromX to above delta values */
  struct XPointArray XPA;	/* values for X plot points argument */
  int StepIndex, NumberOfSteps;	/* loop control */

  NumberOfSteps = 10;		/* dummy */

/* figure out the deltas between from and to coordinate values */

  XIncrement = ToX - FromX;
  YIncrement = ToY - FromY;

/* set up initial values of current X and Y values
 * The integer parts are copies of FromX and FromY.
 * The fraction parts are 1/2 to automagically provide roundoff for the
 * coordinate which is not going in unit steps.
 */

  CurrentX.DividedValue.IntegerPart = (short) FromX;
  CurrentX.DividedValue.FractionPart = PointFormatOneHalf;
  CurrentY.DividedValue.IntegerPart = (short) FromY;
  CurrentY.DividedValue.FractionPart = PointFormatOneHalf;

/* now actually calculate and plot the points */

  for (StepIndex = 0; StepIndex < NumberOfSteps; StepIndex++)
    {
      CurrentX.CombinedValue.CombinedParts += XIncrement;
      CurrentY.CombinedValue.CombinedParts += YIncrement;
      XPA.x = CurrentX.DividedValue.IntegerPart;
      XPA.y = CurrentY.DividedValue.IntegerPart;
      foo(&XPA);
    }
}

------------------------------end of code------------------------------

When the above program is compiled gcc -S, the lines for XPA.x = and
XPA.y = produce:

	movew a6@(-4),a6@(-24)
	movew a6@(-8),a6@(-22)

, whereas when compiled gcc -O -S they produce:

	bfexts d4{#0:#16},d0
	movew d0,a6@(-4)
	bfexts d3{#0:#16},d0
	movew d0,a6@(-2)

.  (In the larger program, or possibly it was with 1.33, the code used
movew, extl, movew .  I will assume {yeah, I know that's the wrong thing to
do, but I expect that to change if you change this} that is because of the
same things that are happening here.)

The optimized version "probably" should use:
	movew d4,a6@(-4)
	movew d3,a6@(-2)
?

The compiler is:
	gcc version 1.34
, compiled with:
	tm-sun3-nfp.h
	m68k.md
, under:
	SunOS v3.5
, on a:
	Sun 3