Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC][GlobalISel] Use Builders in MatchTable #65955

Merged
merged 3 commits into from
Oct 16, 2023

Conversation

Pierre-vh
Copy link
Contributor

@Pierre-vh Pierre-vh commented Sep 11, 2023

The MatchTableExecutor did not use the MachineIRBuilder but instead created instructions ad-hoc.
Making it use a Builder has the benefit that any observer added by a combine is now notified when instructions are created by MIR patterns.

Another benefit is that it allows me to improve how constants are created in apply MIR patterns.
MachineIRBuilder::buildConstant automatically handles splats for us, this means that we may change addCImm to use that and handle vector cases automatically.

@arsenm
Copy link
Contributor

arsenm commented Sep 11, 2023

Currently you're only supposed to push one patch per pull request, you can just pre-push the test regeneration

@Pierre-vh Pierre-vh force-pushed the mirbuilder-in-mt branch 2 times, most recently from 4effc7e to facbc26 Compare September 12, 2023 08:41
Pierre-vh added a commit to Pierre-vh/llvm-project that referenced this pull request Sep 12, 2023
Use ``MachineIRBuilder::buildConstant`` to emit typed immediates in 'apply' MIR patterns.
This allows us to seamlessly handle vector cases, wherre a ``G_BUILD_VECTOR`` is needed to create a splat.

Depends on llvm#65955
@arsenm
Copy link
Contributor

arsenm commented Sep 12, 2023

I'm not really a fan of observers. Why does the match table need these? The execution should know precisely what it's doing without tracking other dynamic context?

@Pierre-vh
Copy link
Contributor Author

I'm not really a fan of observers. Why does the match table need these? The execution should know precisely what it's doing without tracking other dynamic context?

We still use C++ most of the time, and it's impossible for the MatchTable to know what's going on in there unless it uses an observer, so I thought it'd be a nice change to use an observer for tracking all changes.
Likewise, when we use builder functions, like in #66077, we have no way of knowing how many insts were actually built without using a builder.

We can do without the builder, but then flag propagation will be a bit broken.

The MatchTableExecutor did not use the MachineIRBuilder nor Observers to build instructions.
This meant that it only had a very superficial view of what's going on when rules are being applied. Custom code could create insts that the executor didn't know about.

Using a builder & an observer allows it to collect any instruction that's created as long as the same builder is used by the supporting C++ code. For instance, flags are propagated more thoroughly now.

Another benefit that may come later is that I'm trying to improve how constants are created in apply MIR patterns.
`MachineIRBuilder::buildConstant` automatically handles splats for us,
this means that we may change `addCImm` to use that and handle vector cases automatically.
Copy link
Collaborator

@qcolombet qcolombet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it makes sense to use MachineInstrBuilder in general.
Regarding Observes, I think it makes sense (maybe?) to use them to manage the worklist of things that needs to be combined/selected, but it is a no-no IMHO for flag propagation.

@Pierre-vh
Copy link
Contributor Author

I reverted the observer changes, so now it's just adding the MachineIRBuilder and nothing else changes pretty much.
It's all I need to implement the other patches in this series

@github-actions
Copy link

⚠️ C/C++ code formatter, clang-format found issues in your code. ⚠️

You can test this locally with the following command:
git-clang-format --diff fe7fe6d3437da98017b93c99737e421c35e52b7b 06e1fb6ea742d86c50ce410a235893df09e07f48 -- llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp llvm/utils/TableGen/GlobalISelEmitter.cpp
View the diff from clang-format here.
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h
index 1a0a0f46cc73..6f0f9a6a46c7 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h
@@ -52,12 +52,11 @@ bool GIMatchTableExecutor::executeMatchTable(
     const PredicateBitset &AvailableFeatures,
     CodeGenCoverage *CoverageInfo) const {
 
-
   uint64_t CurrentIdx = 0;
   SmallVector<uint64_t, 4> OnFailResumeAt;
   NewMIVector OutMIs;
 
-  GISelChangeObserver* Observer = Builder.getObserver();
+  GISelChangeObserver *Observer = Builder.getObserver();
   // Bypass the flag check on the instruction, and only look at the MCInstrDesc.
   bool NoFPException = !State.MIs[0]->getDesc().mayRaiseFPException();
 
@@ -907,13 +906,12 @@ bool GIMatchTableExecutor::executeMatchTable(
       if (NewInsnID >= OutMIs.size())
         OutMIs.resize(NewInsnID + 1);
 
-      MachineInstr* OldMI = State.MIs[OldInsnID];
-      if(Observer)
+      MachineInstr *OldMI = State.MIs[OldInsnID];
+      if (Observer)
         Observer->changingInstr(*OldMI);
-      OutMIs[NewInsnID] = MachineInstrBuilder(*OldMI->getMF(),
-                                              OldMI);
+      OutMIs[NewInsnID] = MachineInstrBuilder(*OldMI->getMF(), OldMI);
       OutMIs[NewInsnID]->setDesc(TII.get(NewOpcode));
-      if(Observer)
+      if (Observer)
         Observer->changedInstr(*OldMI);
       DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx << ": GIR_MutateOpcode(OutMIs["
@@ -1256,7 +1254,7 @@ bool GIMatchTableExecutor::executeMatchTable(
       // pointer in the builder.
       if (Builder.getInsertPt() == MI)
         Builder.setInsertPt(*MI->getParent(), ++MI->getIterator());
-      if(Observer)
+      if (Observer)
         Observer->erasingInstr(*MI);
       MI->eraseFromParent();
       break;

@Pierre-vh Pierre-vh requested a review from qcolombet October 9, 2023 11:13
@Pierre-vh
Copy link
Contributor Author

Ping :)

Copy link
Contributor

@jayfoad jayfoad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks reasonable to me.

@Pierre-vh
Copy link
Contributor Author

@qcolombet can this land? Thanks

@Pierre-vh Pierre-vh merged commit 96e473a into llvm:main Oct 16, 2023
Pierre-vh added a commit to Pierre-vh/llvm-project that referenced this pull request Oct 16, 2023
Use ``MachineIRBuilder::buildConstant`` to emit typed immediates in 'apply' MIR patterns.
This allows us to seamlessly handle vector cases, wherre a ``G_BUILD_VECTOR`` is needed to create a splat.

Depends on llvm#65955
@qcolombet
Copy link
Collaborator

@qcolombet can this land? Thanks

Yep, looks fine

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants