This is an archive of the discontinued LLVM Phabricator instance.

[Outliner] Add tail call support
ClosedPublic

Authored by paquette on Mar 6 2017, 4:18 PM.

Details

Summary

Major changes:
This commit adds tail-call support to the outliner. This works by making terminators/returns legal to outline if they are either already tail-calls, or they're the last instruction in a function. By doing this, we get two major benefits:

  1. Exposure of new outlining candidates. There could be a repeated substring that was previously too short to outline which is sometimes adjacent to a return. The added return instruction could make it beneficial to outline.
  1. Saved instructions. On x86-64, if we can tail call a candidate, we simply outline the terminator/return along with the candidate, saving us a return in tail-called cases. On other targets, this is more significant. For example, if we outline a candidate as a tail-call on ARM64, we can avoid saving/restoring the link register at the call-site, saving two instructions per outlined call.

Minor changes:

  • Changes to machine-outliner.ll test to ensure that it won't break if the order of outlined functions changes
  • Expanded on the comments on the outlining hooks in TargetInstrInfo.h

Diff Detail

Event Timeline

paquette created this revision.Mar 6 2017, 4:18 PM
MatzeB edited edge metadata.Mar 7 2017, 5:45 PM

Wouldn't the things you do for tail calls here apply in the same way to all forms of returning instructions (MachineInstr::isReturn()), I would assume sequences ending in a return are even more common than tail calls.

MatzeB added a comment.Mar 7 2017, 6:03 PM

While there are (unrelated?) test changes, I see no test for the new functionality added.

MatzeB added a comment.Mar 7 2017, 6:10 PM

Is it possible to avoid the code dealing with ReturnIDs and the new TailCall instruction type, simply by taking the last instruction of an outlined sequence and calling TII::isTailCall() (or MachineInstr::isReturn()) on it to determine whether we outline a sequence ending in one?

lib/CodeGen/MachineOutliner.cpp
519

This can be const.

paquette updated this revision to Diff 91106.Mar 8 2017, 4:55 PM

Removed the extra instruction type for tail calls and fixed up the other couple minor things.

MatzeB added a comment.Mar 9 2017, 4:49 PM

The code looks good to me, but this still lacks a test!

include/llvm/Target/TargetInstrInfo.h
1145

This looks unintentional (rebaseing didn't take r296901 into account probably).

lib/CodeGen/MachineOutliner.cpp
924

seems unrelated.

1199–1200

isReturn() and isTailCall() imply isTerminator() so it should be enough to check just that.

1231–1233

same as above.

lib/Target/X86/X86InstrInfo.cpp
10421–10423

I still wonder if things would just work if you change this to:
if (MI.isTerminator() && MI->getParent()->succ_empty()) so you can catch returns or noreturn functions such as exit() or abort() as well.

If I miss something then go ahead with the current change. I just have the feeling that one of the next commits will just start renaming all the IsTailCall to something like ExitsFunction anyway...

10426

isReturn() implies isTerminator().

10450–10460

Things like improving comments can be committed right away without review (people that care can do post-commit review). This has the added benefits that the actual reviews become smaller.

paquette updated this revision to Diff 91593.Mar 13 2017, 11:05 AM
paquette marked 7 inline comments as done.

Added a test case, removed the tail call MachineOutlinerInstrType.

This also no longer has anything to do with the stack fixups patch.

MatzeB accepted this revision.Mar 13 2017, 11:24 AM

LGTM with nitpicks addressed.

test/CodeGen/X86/machine-outliner-tailcalls.ll
9

You can probably remove the !tbaa bits

27–30

This can be removed if the tbaa bits are gone.

This revision is now accepted and ready to land.Mar 13 2017, 11:24 AM
echristo edited edge metadata.Mar 13 2017, 6:06 PM

The boolean parameter threaded through seems a bit unwieldy. Would it be better to either a) add a call that said e.g. TII.numInstrsForCallReturn(), or b) just assume 1?

Also minor coding convention nit, single statement ifs don't need a { } :)

-eric

Hi Jessica,

I noticed that this was committed without addressing my feedback about the boolean parameters, what's up? :)

-eric

Hi Jessica,

I noticed that this was committed without addressing my feedback about the boolean parameters, what's up? :)

-eric

Oh whoops. I'm scatterbrained, that's what's up. I'll remove it in the next patch.

Actually, the next patch should end up re-architecting a lot of this so that I can handle some more variations on how functions should be outlined/constructed for the AArch64 outliner. Since we're *kind of* talking about this sort of thing, I'll just brain-dump what I'm thinking in here, just to verify whether or not it'd accomplish what you were getting at.

I was thinking was that everything that talks with the target should be in terms of the start/end MachineBasicBlock::iterators for each candidate. The target would then decide how/if that candidate should be outlined. This would mean that the outliner wouldn't have to actually know *how* things are outlined at all, which would make it easier to add target-specific features in the future.

For example,

getOutliningBenefit(size_t SequenceSize, size_t Occurrences, bool CanBeTailCall)

would become something like

callOverhead(MachineBasicBlock::iterator StartIt, MachineBasicBlock::iterator EndIt)
functionOverhead(MachineBasicBlock::iterator StartIt, MachineBasicBlock::iterator EndIt)

And then the number of instructions taken up by an outlined sequence could be redefined as

callOverhead(StartIt, EndIt)* NumOccurrences + functionOverhead(StartIt, EndIt) + SequenceSize

I think this is somewhat less cumbersome and nicely divorces target-specific stuff from the main outlining pass. I do worry that it moves a little too much of the pass' functionality into [TargetName]InstrInfo though. What do you think?

I think that sounds awesome :)

I'm also taking a look at your other patch.

MatzeB closed this revision.Sep 26 2017, 2:29 PM

Looks like this was committed in r297653