This is an archive of the discontinued LLVM Phabricator instance.

[Outliner] Add outliner for AArch64
ClosedPublic

Authored by paquette on Mar 13 2017, 3:00 PM.

Details

Summary

This patch adds an outliner for AArch64. It adds the outliner target hooks to AArch64InstrInfo.cpp and AArch64InstrInfo.cpp. This allows for outlining using the -mno-red-zone and -enable-machine-outliner flags.

The main difference from the X86-64 outliner is the inclusion of post-outlining stack fixups. A function, getPostOutliningFixup is added to determine if an instruction that uses SP can be fixed up post-outlining. After each outlined function is created, fixupPostOutline is called on the MachineBasicBlock in that function, and recalculates stack offsets using getPostOutliningFixup.

For a simpler example of how this works, see https://reviews.llvm.org/D30797

Diff Detail

Event Timeline

paquette created this revision.Mar 13 2017, 3:00 PM
MatzeB edited edge metadata.Mar 13 2017, 5:24 PM

This looks good! I only see one real problem right now, the rest is the usual coding style/nitpicking.

  • ARM instructions only use a limited number of bits to encode immediate values. I don't see the stack fixup code checking whether the adjusted value still fits the instruction encodings.
lib/Target/AArch64/AArch64InstrInfo.cpp
4278

Typing MachineOperand & here isn't that much longer and friendlier to the reader.

4287–4361

This is an awful lot of instruction specifics here. This list is dangerous to become stale/out of date when people add instruction in the future. Better try to move this into AArch64InstrInfo where the chance is higher that people will see and update it. Or better try to share code with one of the existing functions there (AArch64InstrInfo::getMemOpBaseRegImmOfsWidth looks similar, do you need modifications to the API to reuse it?)

4375–4377

That's a bit of a pity. Shouldn't be too hard to determine the effected LOH entries and throw them away as part of an upcoming patch (I would consider outlining more important than having a linker optimization hint).

4386

Maybe make a slightly higher level statement: // Does the function end here?

4407–4408

Could you check whether you really need the getDesc() checks? I was hoping only the X86 target has these missing operand bugs... Same with the next if.

4435

Less auto please.

4436

The getNumExplicitOperands()-1 seems somewhat magical, is there an AArch64InstrInfo function for it? If not consider creating one.

4486–4509

Suggestion for followup patches: Use the LivePhysReg utility to discover unused registers in the outlined sequence so you can get away without a load/store in some cases.

lib/Target/AArch64/AArch64InstrInfo.h
258

The llvm:: prefix is probably unnecessary.

268

I should have noticed in the main outliner review already: When you use an instruction iterator to signal the insertion point, I'd recommend calling it InsertBefore or InsertAfter to make it obvious whether we insert before or after the given instruction...
(Feel free to fix this on the side without review)

paquette updated this revision to Diff 92071.Mar 16 2017, 3:22 PM
paquette marked 10 inline comments as done.

Updated diff to address comments

Major changes

  • Added getScale to AArch64InstrInfo.h. This returns the scale of an appropriate instruction.
  • Added getMemOpBaseRegImmOfsOffsetOperand to hide the magical getNumExplicitOperands()-1 stuff.
  • Added isEncodableLdStOffset, which determines if the updated offset would overflow.

I noticed that the scale of an instruction is calculated in lots of places throughout AArch64InstrInfo.cpp. It might be good to refactor these to use something like getScale in the future to prevent breakage, since it seems like in all these places roughly the same instructions are being used. (I tried shoehorning the scale calculation into getMemOpBaseRegImmOfsWidth, but it seemed a little kludgey.)

MatzeB added inline comments.Mar 16 2017, 5:32 PM
lib/Target/AArch64/AArch64InstrInfo.cpp
1410–1463

Seeing that this is another instance of information about every load/store instruction. How about emitting this information as well if we go for something like getMemOpInfo()?

lib/Target/AArch64/AArch64InstrInfo.h
220

We should only put short and performance critical functions into a header (and well templates force you sometimes).

It shouldn't be too hard to share code with getMemOpBaseRegImmOfsWidth() and for maintenance reasons we really should do so:

  • Add a new function similar to this:
/// Returns true if opcode \p Opc is a memory operation and set \p Scale and \p Width
/// accordingly.
bool getMemOpInfo(unsigned Opcode, unsigned &Scale, unsigned &Width) {
   switch (Opc) {
      // Move stuff from getMemOpBaseRegImmOfsWidth() here
   }
}

bool AArch64InstrInfo::getMemOpBaseRegImmOfsWidth(...) {
   // ... keep the beginning as is ...
   unsigned Scale = 0;
   if (!getMemOpInfo(LdSt.getOpcode(), Width, Scale))
     return false;
   // ... keep end as is ...
}

// Every use of getScale() can now call getMemOpInfo() and just ignore the Width value
paquette updated this revision to Diff 92200.Mar 17 2017, 2:11 PM
paquette marked 2 inline comments as done.

Updated the diff to address comments.

Changes

  • Replaced getScale with getMemOpInfo.
  • Replaced the switch statement in getMemOpBaseRegImmOfsWidth with a call to getMemOpInfo.

In the future, getMemOpInfo can probably be expanded so that the other functions that use large switch statements over all loads/stores use it (or something similar) instead.

MatzeB accepted this revision.Mar 17 2017, 2:18 PM

LGTM, just check that return false branch (see below).

We should also have a test for the behavior on overflowing offset operands. However I see that this is really hard to test with .ll files so go ahead for now but please add a TODO and implement it later when we have fixed .mir parsing to work with passes that create new functions like the outliner.

lib/Target/AArch64/AArch64InstrInfo.cpp
1691

This had

default: return false;

before, was this case impossible to hit or do we need if (!getMemOpInfo()) return false?

This revision is now accepted and ready to land.Mar 17 2017, 2:18 PM
MatzeB closed this revision.Sep 26 2017, 2:30 PM

Looks like this was committed in r298162