[RFC] Remat Enhancements

I have a set of changes that enhances rematerialization to handle more
kinds of loads, specifically loads with multiple address registers.
This is a big win for some codes on x86.

I plan to send these up ASAP but I want to solicit a bit of guidance
first.

The change requires that live interval analysis be able to determine
whether and instruction is a load and whether an instruction writes to
memory. Here's how I've handled these two questions:

- Add an isLoad member to TargetInstrInfo with a corresponding
  implementation in the X86 target consisting of a switch on all
  of the load-type opcodes. By default isLoad returns false so
  that false negatives are possible.

- Add a writesMemory member to TargetInstrInfo with a corresponding
  implementation in the XD86 target. The target implemenmtation is both
  a switch on store-type opcodes and a check to see whether a
  MachineInstr has write-type MachineMemOperands. The default
  implementation returns "false" but "true" might be a safer default
  (false positives).

The remat code itself identifies load instructions and checks to see
whether it interferes with any instructions that write to memory.

Are isLoad and writesMemory reasonable implementations of these queries?
Are there other routes that might be better? I'm particularly
interested in opinions about false positives/negatives. What's the safe
default? In either case comments must indicate the possibility of
"incorrect" answers.

Finally, are MachineMemOperands guaranteed (modulo bugs, of course) to
be preserved at least through regalloc?

                                 -Dave

I have a set of changes that enhances rematerialization to handle more
kinds of loads, specifically loads with multiple address registers.
This is a big win for some codes on x86.

That's great, but I really wish you would discuss the design of these things publicly, and not develop features on long-running secret branches. If you secretly start out in the wrong direction, you could be wasting a lot of your time.

I plan to send these up ASAP but I want to solicit a bit of guidance
first.

The change requires that live interval analysis be able to determine
whether and instruction is a load and whether an instruction writes to
memory.

Just use MI->mayLoad(), MI->mayStore().

[And live interval analysis shouldn't be involved in remat these days.]

The remat code itself identifies load instructions and checks to see
whether it interferes with any instructions that write to memory.

How does that affect compile time?

Finally, are MachineMemOperands guaranteed (modulo bugs, of course) to
be preserved at least through regalloc?

They are preserved, but they are not 'guaranteed'. A load or store with missing memops should conservatively be treated as volatile, aliasing everything.

/jakob

Jakob Stoklund Olesen <stoklund@2pi.dk> writes:

That's great, but I really wish you would discuss the design of these
things publicly, and not develop features on long-running secret
branches. If you secretly start out in the wrong direction, you could
be wasting a lot of your time.

I don't have a choice. I have to get patches approved after I already
have them. In this case, I had a week to get the feature done to meet a
deadline so there was no time for previous discussion. I really don't
like that I'm under these constriants but that's the way it is,
unfortunately.

The change requires that live interval analysis be able to determine
whether and instruction is a load and whether an instruction writes to
memory.

Just use MI->mayLoad(), MI->mayStore().

Does this also account for arithmetic instructions with memops? These
interfaces didn't exist in 2.9.

[And live interval analysis shouldn't be involved in remat these days.]

Ok, I'm working off 2.9 so I'll have to update for trunk. That's no
problem.

The remat code itself identifies load instructions and checks to see
whether it interferes with any instructions that write to memory.

How does that affect compile time?

I haven't noticed any impact.

Finally, are MachineMemOperands guaranteed (modulo bugs, of course) to
be preserved at least through regalloc?

They are preserved, but they are not 'guaranteed'. A load or store
with missing memops should conservatively be treated as volatile,
aliasing everything.

Right, that's what I do. If mayLoad() and mayStore() cover all
instructions with memory semantics, it should be fine.

Thanks!

                               -Dave

dag@cray.com (David A. Greene) writes:

The change requires that live interval analysis be able to determine
whether and instruction is a load and whether an instruction writes to
memory.

Just use MI->mayLoad(), MI->mayStore().

Does this also account for arithmetic instructions with memops? These
interfaces didn't exist in 2.9.

This is important because if mayLoad includes arithmetic instructions
with source memops (which I assume it will), it is unsuitable for remat
analysis. I don't think we want to remat general arithmetic quite yet.
At least that's not the intent of my change. I'll need some way to
identify "real" loads and I don't know of any other way other than
listing opcodes. Ideas?

                                 -Dave

The target sets the isRematerializable bit on opcodes that are suitable for remat. That should be sufficient.

You should also check the 'canFoldAsLoad' mechanism.

/jakob

Jakob Stoklund Olesen <stoklund@2pi.dk> writes:

This is important because if mayLoad includes arithmetic instructions
with source memops (which I assume it will), it is unsuitable for remat
analysis. I don't think we want to remat general arithmetic quite yet.
At least that's not the intent of my change. I'll need some way to
identify "real" loads and I don't know of any other way other than
listing opcodes. Ideas?

The target sets the isRematerializable bit on opcodes that are
suitable for remat. That should be sufficient.

Ok, that should work.

You should also check the 'canFoldAsLoad' mechanism.

Will do. Thanks for the pointers!

                             -Dave