[PATCH] D147532: [MachineLateInstrsCleanup] Improve compile time for huge functions.
Jonas Paulsson via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Sun Apr 30 04:58:37 PDT 2023
jonpa marked an inline comment as done.
jonpa added a comment.
It seems that this would result in this loop:
for (auto DefI = MBBDefs.begin(); DefI != MBBDefs.end();) {
Register Reg = DefI->first;
if (MI.modifiesRegister(Reg, TRI)) {
MBBDefs.erase(DefI++);
MBBKills.erase(Reg);
continue;
} else if (MI.findRegisterUseOperandIdx(Reg, false /*isKill*/, TRI) != -1)
// Keep track of the last use seen so far.
MBBKills[Reg] = &MI;
DefI++;
}
I find that acceptable, but the iteration logic is slightly complicated. That's why I chose to ignore the extra lookup when calling erase(Reg) in the first place:
for (auto DefI : llvm::make_early_inc_range(MBBDefs)) {
Register Reg = DefI.first;
if (MI.modifiesRegister(Reg, TRI)) {
MBBDefs.erase(Reg);
MBBKills.erase(Reg);
} else if (MI.findRegisterUseOperandIdx(Reg, false /*isKill*/, TRI) != -1)
// Keep track of the last use seen so far.
MBBKills[Reg] = &MI;
}
I compared both these versions just now on a z15 with your test case, but found no difference:
---User Time--- --System Time-- --User+System-- ---Wall Time--- --- Name ---
itr: 4.8783 ( 0.4%) 0.0011 ( 0.0%) 4.8794 ( 0.4%) 4.8833 ( 0.4%) Machine Late Instructions Cleanup Pass
reg: 4.8384 ( 0.4%) 0.0009 ( 0.0%) 4.8393 ( 0.4%) 4.8439 ( 0.4%) Machine Late Instructions Cleanup Pass
I guess this could mean that this test case does a lot of reuse of the earlier Candidate, so it doesn't call erase() here that much, maybe.
On SPEC/SystemZ they both average 0.52% compile time across all files, so there is no difference there either.
The situation may be different on other systems, I suppose. I was using GCC version used to build clang: 12.2.1. Do you see any compile time difference at all on your platform?
I would personally vote for the readability (ignore the erase(Reg) potential overhead), but I will let you the reviewer(s) decide :)
================
Comment at: llvm/lib/CodeGen/MachineLateInstrsCleanup.cpp:236
+ if (MI.modifiesRegister(Reg, TRI)) {
+ MBBDefs.erase(Reg);
+ MBBKills.erase(Reg);
----------------
vpykhtin wrote:
> jonpa wrote:
> > jonpa wrote:
> > > vpykhtin wrote:
> > > > vpykhtin wrote:
> > > > > Sorry, I didn't notice this change first.
> > > > >
> > > > > You can still use erase by iterator (it's slightly faster than another lookup) because you're using make_early_inc_range.
> > > > bad advice - DefI is already incremented after Register Reg = DefI.first.
> > > >
> > > > May be you can leave previous variant of iteration, you can increment the iterator like this:
> > > >
> > > > MBBDefs.erase(DefI++) instead of DefI = MBBDefs.erase(DefI)
> > > >
> > > >
> > > Yeah - I went for readability at first here as I did not see any change in compile time.
> > I did not find anything to convince me 100% that this use of erase with iterator is legal, so I will have to trust you on this ;-)
> >
> > I think the readability is ok now as well with this.
> >
> Now you're incrementing DefI after erase and in general this is incorrect for STL containers (though it's not the case here) because erase invalidates iterators to erased elements.
>
> MBBDefs.erase(DefI++) works because arguments are fully evaluated before function call, so this is equivalent to:
>
> auto DefIBefore = DefI;
> ++DefI; // Now DefI is valid after erase
> MBBDefs.erase(DefIBefore);
Sorry,I thought you were implying that increment after erase() was fine with this SmallDenseMap...
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D147532/new/
https://reviews.llvm.org/D147532
More information about the llvm-commits
mailing list