-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
[TableGen] Use buildConstant to emit apply pattern immediates #66077
Conversation
@llvm/pr-subscribers-llvm-globalisel ChangesNOTE: This is part of a stack. Please only review the last commit, see #65955 to review the first commit. Use -- Patch is 97.20 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/66077.diff 21 Files Affected:
diff --git a/llvm/docs/GlobalISel/MIRPatterns.rst b/llvm/docs/GlobalISel/MIRPatterns.rst index 51d1850a1236039..fa70311f48572de 100644 --- a/llvm/docs/GlobalISel/MIRPatterns.rst +++ b/llvm/docs/GlobalISel/MIRPatterns.rst @@ -257,8 +257,8 @@ Common Pattern #3: Emitting a Constant Value When an immediate operand appears in an 'apply' pattern, the behavior depends on whether it's typed or not. -* If the immediate is typed, a ``G_CONSTANT`` is implicitly emitted - (= a register operand is added to the instruction). +* If the immediate is typed, ``MachineIRBuilder::buildConstant`` is used + to create a ``G_CONSTANT``. A ``G_BUILD_VECTOR`` will be used for vectors. * If the immediate is untyped, a simple immediate is added (``MachineInstrBuilder::addImm``). diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h index 2b0733cf9353e6c..89c0b097281ddfa 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h @@ -18,6 +18,7 @@ #include "llvm/ADT/Bitset.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h" #include "llvm/CodeGen/GlobalISel/Utils.h" #include "llvm/CodeGen/LowLevelType.h" #include "llvm/CodeGen/MachineFunction.h" @@ -40,6 +41,7 @@ class APInt; class APFloat; class GISelKnownBits; class MachineInstr; +class MachineIRBuilder; class MachineInstrBuilder; class MachineFunction; class MachineOperand; @@ -291,6 +293,11 @@ enum { /// - Opcode - The new opcode to use GIR_BuildMI, + /// Builds a constant and stores its result in a TempReg. + /// - TempRegID - Temp Register to define. + /// - Imm - The immediate to add + GIR_BuildConstant, + /// Copy an operand to the specified instruction /// - NewInsnID - Instruction ID to modify /// - OldInsnID - Instruction ID to copy from @@ -501,10 +508,25 @@ class GIMatchTableExecutor { } protected: + /// Observer used by \ref executeMatchTable to record all instructions created + /// by the rule. + class GIMatchTableObserver : public GISelChangeObserver { + public: + virtual ~GIMatchTableObserver(); + + void erasingInstr(MachineInstr &MI) override { CreatedInsts.erase(&MI); } + void createdInstr(MachineInstr &MI) override { CreatedInsts.insert(&MI); } + void changingInstr(MachineInstr &MI) override {} + void changedInstr(MachineInstr &MI) override {} + + // Keeps track of all instructions that have been created when applying a + // rule. + SmallDenseSet CreatedInsts; + }; + using ComplexRendererFns = std::optional, 4>>; using RecordedMIVector = SmallVector; - using NewMIVector = SmallVector; struct MatcherState { std::vector Renderers; @@ -555,15 +577,15 @@ class GIMatchTableExecutor { /// and false otherwise. template - bool executeMatchTable( - TgtExecutor &Exec, NewMIVector &OutMIs, MatcherState &State, - const ExecInfoTy - &ISelInfo, - const int64_t *MatchTable, const TargetInstrInfo &TII, - MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, - const RegisterBankInfo &RBI, const PredicateBitset &AvailableFeatures, - CodeGenCoverage *CoverageInfo, - GISelChangeObserver *Observer = nullptr) const; + bool executeMatchTable(TgtExecutor &Exec, MatcherState &State, + const ExecInfoTy &ExecInfo, + MachineIRBuilder &Builder, const int64_t *MatchTable, + const TargetInstrInfo &TII, MachineRegisterInfo &MRI, + const TargetRegisterInfo &TRI, + const RegisterBankInfo &RBI, + const PredicateBitset &AvailableFeatures, + CodeGenCoverage *CoverageInfo) const; virtual const int64_t *getMatchTable() const { llvm_unreachable("Should have been overridden by tablegen if used"); @@ -592,7 +614,7 @@ class GIMatchTableExecutor { } virtual void runCustomAction(unsigned, const MatcherState &State, - NewMIVector &OutMIs) const { + ArrayRef OutMIs) const { llvm_unreachable("Subclass does not implement runCustomAction!"); } diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h index 883c1ca0fe350b0..92a1eb561fb10ae 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h @@ -18,6 +18,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h" #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h" +#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" #include "llvm/CodeGen/GlobalISel/Utils.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineOperand.h" @@ -42,17 +43,33 @@ namespace llvm { template bool GIMatchTableExecutor::executeMatchTable( - TgtExecutor &Exec, NewMIVector &OutMIs, MatcherState &State, + TgtExecutor &Exec, MatcherState &State, const ExecInfoTy &ExecInfo, - const int64_t *MatchTable, const TargetInstrInfo &TII, - MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, - const RegisterBankInfo &RBI, const PredicateBitset &AvailableFeatures, - CodeGenCoverage *CoverageInfo, GISelChangeObserver *Observer) const { + MachineIRBuilder &Builder, const int64_t *MatchTable, + const TargetInstrInfo &TII, MachineRegisterInfo &MRI, + const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI, + const PredicateBitset &AvailableFeatures, + CodeGenCoverage *CoverageInfo) const { + + // Setup observer + GIMatchTableObserver MTObserver; + GISelObserverWrapper Observer(&MTObserver); + if (auto *CurObs = Builder.getChangeObserver()) + Observer.addObserver(CurObs); + + // TODO: Set MF delegate? + + // Setup builder. + auto RestoreOldObserver = Builder.setTemporaryChangeObserver(Observer); uint64_t CurrentIdx = 0; SmallVector OnFailResumeAt; + // We also record MachineInstrs manually in this vector so opcodes can address + // them. + SmallVector OutMIs; + // Bypass the flag check on the instruction, and only look at the MCInstrDesc. bool NoFPException = !State.MIs[0]->getDesc().mayRaiseFPException(); @@ -71,14 +88,16 @@ bool GIMatchTableExecutor::executeMatchTable( return RejectAndResume; }; - auto propagateFlags = [=](NewMIVector &OutMIs) { - for (auto MIB : OutMIs) { + auto propagateFlags = [&]() { + for (auto *MI : MTObserver.CreatedInsts) { // Set the NoFPExcept flag when no original matched instruction could // raise an FP exception, but the new instruction potentially might. uint16_t MIBFlags = Flags; - if (NoFPException && MIB->mayRaiseFPException()) + if (NoFPException && MI->mayRaiseFPException()) MIBFlags |= MachineInstr::NoFPExcept; - MIB.setMIFlags(MIBFlags); + Observer.changingInstr(*MI); + MI->setFlags(MIBFlags); + Observer.changedInstr(*MI); } return true; @@ -901,6 +920,7 @@ bool GIMatchTableExecutor::executeMatchTable( OutMIs[NewInsnID] = MachineInstrBuilder(*State.MIs[OldInsnID]->getMF(), State.MIs[OldInsnID]); OutMIs[NewInsnID]->setDesc(TII.get(NewOpcode)); + MTObserver.CreatedInsts.insert(OutMIs[NewInsnID]); DEBUG_WITH_TYPE(TgtExecutor::getName(), dbgs() << CurrentIdx << ": GIR_MutateOpcode(OutMIs[" << NewInsnID << "], MIs[" << OldInsnID << "], " @@ -914,14 +934,23 @@ bool GIMatchTableExecutor::executeMatchTable( if (NewInsnID >= OutMIs.size()) OutMIs.resize(NewInsnID + 1); - OutMIs[NewInsnID] = BuildMI(*State.MIs[0]->getParent(), State.MIs[0], - MIMetadata(*State.MIs[0]), TII.get(Opcode)); + OutMIs[NewInsnID] = Builder.buildInstr(Opcode); DEBUG_WITH_TYPE(TgtExecutor::getName(), dbgs() << CurrentIdx << ": GIR_BuildMI(OutMIs[" << NewInsnID << "], " << Opcode << ")\n"); break; } + case GIR_BuildConstant: { + int64_t TempRegID = MatchTable[CurrentIdx++]; + int64_t Imm = MatchTable[CurrentIdx++]; + Builder.buildConstant(State.TempRegisters[TempRegID], Imm); + DEBUG_WITH_TYPE(TgtExecutor::getName(), + dbgs() << CurrentIdx << ": GIR_BuildConstant(TempReg[" + << TempRegID << "], Imm=" << Imm << ")\n"); + break; + } + case GIR_Copy: { int64_t NewInsnID = MatchTable[CurrentIdx++]; int64_t OldInsnID = MatchTable[CurrentIdx++]; @@ -1239,8 +1268,11 @@ bool GIMatchTableExecutor::executeMatchTable( DEBUG_WITH_TYPE(TgtExecutor::getName(), dbgs() << CurrentIdx << ": GIR_EraseFromParent(MIs[" << InsnID << "])\n"); - if (Observer) - Observer->erasingInstr(*MI); + // If we're erasing the insertion point, ensure we don't leave a dangling + // pointer in the builder. + if (Builder.getInsertPt() == MI) + Builder.setInsertPt(*MI->getParent(), ++MI->getIterator()); + Observer.erasingInstr(*MI); MI->eraseFromParent(); break; } @@ -1269,11 +1301,9 @@ bool GIMatchTableExecutor::executeMatchTable( Register Old = State.MIs[OldInsnID]->getOperand(OldOpIdx).getReg(); Register New = State.MIs[NewInsnID]->getOperand(NewOpIdx).getReg(); - if (Observer) - Observer->changingAllUsesOfReg(MRI, Old); + Observer.changingAllUsesOfReg(MRI, Old); MRI.replaceRegWith(Old, New); - if (Observer) - Observer->finishedChangingAllUsesOfReg(); + Observer.finishedChangingAllUsesOfReg(); break; } case GIR_ReplaceRegWithTempReg: { @@ -1288,11 +1318,9 @@ bool GIMatchTableExecutor::executeMatchTable( Register Old = State.MIs[OldInsnID]->getOperand(OldOpIdx).getReg(); Register New = State.TempRegisters[TempRegID]; - if (Observer) - Observer->changingAllUsesOfReg(MRI, Old); + Observer.changingAllUsesOfReg(MRI, Old); MRI.replaceRegWith(Old, New); - if (Observer) - Observer->finishedChangingAllUsesOfReg(); + Observer.finishedChangingAllUsesOfReg(); break; } case GIR_Coverage: { @@ -1309,11 +1337,7 @@ bool GIMatchTableExecutor::executeMatchTable( case GIR_Done: DEBUG_WITH_TYPE(TgtExecutor::getName(), dbgs() << CurrentIdx << ": GIR_Done\n"); - if (Observer) { - for (MachineInstr *MI : OutMIs) - Observer->createdInstr(*MI); - } - propagateFlags(OutMIs); + propagateFlags(); return true; default: llvm_unreachable("Unexpected command"); diff --git a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h index e7db9547f03b694..99b821406b0f893 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h @@ -20,6 +20,7 @@ #include "llvm/CodeGen/TargetOpcodes.h" #include "llvm/IR/DebugLoc.h" #include "llvm/IR/Module.h" +#include "llvm/Support/SaveAndRestore.h" namespace llvm { @@ -364,6 +365,15 @@ class MachineIRBuilder { State.Observer = &Observer; } + GISelChangeObserver *getChangeObserver() const { return State.Observer; } + + // Replaces the change observer with \p Observer and returns an object that + // restores the old Observer on destruction. + SaveAndRestore + setTemporaryChangeObserver(GISelChangeObserver &Observer) { + return SaveAndRestore(State.Observer, &Observer); + } + void stopObservingChanges() { State.Observer = nullptr; } bool isObservingChanges() const { return State.Observer != nullptr; } diff --git a/llvm/lib/CodeGen/GlobalISel/GIMatchTableExecutor.cpp b/llvm/lib/CodeGen/GlobalISel/GIMatchTableExecutor.cpp index 26752369a7711a1..c1ababb8ed852d0 100644 --- a/llvm/lib/CodeGen/GlobalISel/GIMatchTableExecutor.cpp +++ b/llvm/lib/CodeGen/GlobalISel/GIMatchTableExecutor.cpp @@ -21,6 +21,10 @@ using namespace llvm; +GIMatchTableExecutor::GIMatchTableObserver::~GIMatchTableObserver() { + // anchor +} + GIMatchTableExecutor::MatcherState::MatcherState(unsigned MaxRenderers) : Renderers(MaxRenderers) {} diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-sdiv.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-sdiv.mir index e99ee84100a3991..13f9998952e6ed3 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-sdiv.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-sdiv.mir @@ -22,10 +22,10 @@ body: | ; CHECK: liveins: $w0 ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 - ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 3 - ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 -991146299 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = exact G_CONSTANT i32 3 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = exact G_CONSTANT i32 -991146299 ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(s32) = exact G_ASHR [[COPY]], [[C]](s32) - ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[ASHR]], [[C1]] + ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = exact G_MUL [[ASHR]], [[C1]] ; CHECK-NEXT: $w0 = COPY [[MUL]](s32) ; CHECK-NEXT: RET_ReallyLR implicit $w0 %0:_(s32) = COPY $w0 @@ -87,13 +87,13 @@ body: | ; CHECK: liveins: $q0 ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<4 x s32>) = COPY $q0 - ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 3 - ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 -991146299 - ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 954437177 - ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C]](s32), [[C]](s32), [[C]](s32), [[C]](s32) - ; CHECK-NEXT: [[BUILD_VECTOR1:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C1]](s32), [[C2]](s32), [[C1]](s32), [[C2]](s32) + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = exact G_CONSTANT i32 3 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = exact G_CONSTANT i32 -991146299 + ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = exact G_CONSTANT i32 954437177 + ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s32>) = exact G_BUILD_VECTOR [[C]](s32), [[C]](s32), [[C]](s32), [[C]](s32) + ; CHECK-NEXT: [[BUILD_VECTOR1:%[0-9]+]]:_(<4 x s32>) = exact G_BUILD_VECTOR [[C1]](s32), [[C2]](s32), [[C1]](s32), [[C2]](s32) ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(<4 x s32>) = exact G_ASHR [[COPY]], [[BUILD_VECTOR]](<4 x s32>) - ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(<4 x s32>) = G_MUL [[ASHR]], [[BUILD_VECTOR1]] + ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(<4 x s32>) = exact G_MUL [[ASHR]], [[BUILD_VECTOR1]] ; CHECK-NEXT: $q0 = COPY [[MUL]](<4 x s32>) ; CHECK-NEXT: RET_ReallyLR implicit $q0 %0:_(<4 x s32>) = COPY $q0 @@ -115,12 +115,12 @@ body: | ; CHECK: liveins: $q0 ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<4 x s32>) = COPY $q0 - ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 3 - ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 -991146299 - ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C]](s32), [[C]](s32), [[C]](s32), [[C]](s32) - ; CHECK-NEXT: [[BUILD_VECTOR1:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C1]](s32), [[C1]](s32), [[C1]](s32), [[C1]](s32) + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = exact G_CONSTANT i32 3 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = exact G_CONSTANT i32 -991146299 + ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s32>) = exact G_BUILD_VECTOR [[C]](s32), [[C]](s32), [[C]](s32), [[C]](s32) + ; CHECK-NEXT: [[BUILD_VECTOR1:%[0-9]+]]:_(<4 x s32>) = exact G_BUILD_VECTOR [[C1]](s32), [[C1]](s32), [[C1]](s32), [[C1]](s32) ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(<4 x s32>) = exact G_ASHR [[COPY]], [[BUILD_VECTOR]](<4 x s32>) - ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(<4 x s32>) = G_MUL [[ASHR]], [[BUILD_VECTOR1]] + ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(<4 x s32>) = exact G_MUL [[ASHR]], [[BUILD_VECTOR1]] ; CHECK-NEXT: $q0 = COPY [[MUL]](<4 x s32>) ; CHECK-NEXT: RET_ReallyLR implicit $q0 %0:_(<4 x s32>) = COPY $q0 diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizercombiner-ashr-shl-to-sext-inreg.mir b/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizercombiner-ashr-shl-to-sext-inreg.mir index 9e540390dd37f43..9176328d873e619 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizercombiner-ashr-shl-to-sext-inreg.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizercombiner-ashr-shl-to-sext-inreg.mir @@ -15,7 +15,7 @@ body: | ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) - ; CHECK-NEXT: [[SEXT_INREG:%[0-9]+]]:_(s16) = G_SEXT_INREG [[TRUNC]], 8 + ; CHECK-NEXT: [[SEXT_INREG:%[0-9]+]]:_(s16) = exact G_SEXT_INREG [[TRUNC]], 8 ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[SEXT_INREG]](s16) ; CHECK-NEXT: $w0 = COPY [[ANYEXT]](s32) ; CHECK-NEXT: RET_ReallyLR implicit $w0 @@ -75,7 +75,7 @@ body: | ; CHECK: liveins: $d0 ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $d0 - ; CHECK-NEXT: [[SEXT_INREG:%[0-9]+]]:_(<4 x s16>) = G_SEXT_INREG [[COPY]], 8 + ; CHECK-NEXT: [[SEXT_INREG:%[0-9]+]]:_(<4 x s16>) = exact G_SEXT_INREG [[COPY]], 8 ; CHECK-NEXT: $d0 = COPY [[SEXT_INREG]](<4 x s16>) ; CHECK-NEXT: RET_ReallyLR implicit $d0 %0:_(<4 x s16>) = COPY $d0 diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/combine-fma-add-mul-pre-legalize.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/combine-fma-add-mul-pre-legalize.mir index ee775dc674cfecd..90df73e85c9e7c7 100644 --- a/llvm/test/Cod... |
@llvm/pr-subscribers-backend-aarch64 ChangesNOTE: This is part of a stack. Please only review the last commit, see #65955 to review the first commit. Use -- Patch is 97.20 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/66077.diff 21 Files Affected:
diff --git a/llvm/docs/GlobalISel/MIRPatterns.rst b/llvm/docs/GlobalISel/MIRPatterns.rst index 51d1850a1236039..fa70311f48572de 100644 --- a/llvm/docs/GlobalISel/MIRPatterns.rst +++ b/llvm/docs/GlobalISel/MIRPatterns.rst @@ -257,8 +257,8 @@ Common Pattern #3: Emitting a Constant Value When an immediate operand appears in an 'apply' pattern, the behavior depends on whether it's typed or not. -* If the immediate is typed, a ``G_CONSTANT`` is implicitly emitted - (= a register operand is added to the instruction). +* If the immediate is typed, ``MachineIRBuilder::buildConstant`` is used + to create a ``G_CONSTANT``. A ``G_BUILD_VECTOR`` will be used for vectors. * If the immediate is untyped, a simple immediate is added (``MachineInstrBuilder::addImm``). diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h index 2b0733cf9353e6c..89c0b097281ddfa 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h @@ -18,6 +18,7 @@ #include "llvm/ADT/Bitset.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h" #include "llvm/CodeGen/GlobalISel/Utils.h" #include "llvm/CodeGen/LowLevelType.h" #include "llvm/CodeGen/MachineFunction.h" @@ -40,6 +41,7 @@ class APInt; class APFloat; class GISelKnownBits; class MachineInstr; +class MachineIRBuilder; class MachineInstrBuilder; class MachineFunction; class MachineOperand; @@ -291,6 +293,11 @@ enum { /// - Opcode - The new opcode to use GIR_BuildMI, + /// Builds a constant and stores its result in a TempReg. + /// - TempRegID - Temp Register to define. + /// - Imm - The immediate to add + GIR_BuildConstant, + /// Copy an operand to the specified instruction /// - NewInsnID - Instruction ID to modify /// - OldInsnID - Instruction ID to copy from @@ -501,10 +508,25 @@ class GIMatchTableExecutor { } protected: + /// Observer used by \ref executeMatchTable to record all instructions created + /// by the rule. + class GIMatchTableObserver : public GISelChangeObserver { + public: + virtual ~GIMatchTableObserver(); + + void erasingInstr(MachineInstr &MI) override { CreatedInsts.erase(&MI); } + void createdInstr(MachineInstr &MI) override { CreatedInsts.insert(&MI); } + void changingInstr(MachineInstr &MI) override {} + void changedInstr(MachineInstr &MI) override {} + + // Keeps track of all instructions that have been created when applying a + // rule. + SmallDenseSet CreatedInsts; + }; + using ComplexRendererFns = std::optional, 4>>; using RecordedMIVector = SmallVector; - using NewMIVector = SmallVector; struct MatcherState { std::vector Renderers; @@ -555,15 +577,15 @@ class GIMatchTableExecutor { /// and false otherwise. template - bool executeMatchTable( - TgtExecutor &Exec, NewMIVector &OutMIs, MatcherState &State, - const ExecInfoTy - &ISelInfo, - const int64_t *MatchTable, const TargetInstrInfo &TII, - MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, - const RegisterBankInfo &RBI, const PredicateBitset &AvailableFeatures, - CodeGenCoverage *CoverageInfo, - GISelChangeObserver *Observer = nullptr) const; + bool executeMatchTable(TgtExecutor &Exec, MatcherState &State, + const ExecInfoTy &ExecInfo, + MachineIRBuilder &Builder, const int64_t *MatchTable, + const TargetInstrInfo &TII, MachineRegisterInfo &MRI, + const TargetRegisterInfo &TRI, + const RegisterBankInfo &RBI, + const PredicateBitset &AvailableFeatures, + CodeGenCoverage *CoverageInfo) const; virtual const int64_t *getMatchTable() const { llvm_unreachable("Should have been overridden by tablegen if used"); @@ -592,7 +614,7 @@ class GIMatchTableExecutor { } virtual void runCustomAction(unsigned, const MatcherState &State, - NewMIVector &OutMIs) const { + ArrayRef OutMIs) const { llvm_unreachable("Subclass does not implement runCustomAction!"); } diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h index 883c1ca0fe350b0..92a1eb561fb10ae 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h @@ -18,6 +18,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h" #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h" +#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" #include "llvm/CodeGen/GlobalISel/Utils.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineOperand.h" @@ -42,17 +43,33 @@ namespace llvm { template bool GIMatchTableExecutor::executeMatchTable( - TgtExecutor &Exec, NewMIVector &OutMIs, MatcherState &State, + TgtExecutor &Exec, MatcherState &State, const ExecInfoTy &ExecInfo, - const int64_t *MatchTable, const TargetInstrInfo &TII, - MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, - const RegisterBankInfo &RBI, const PredicateBitset &AvailableFeatures, - CodeGenCoverage *CoverageInfo, GISelChangeObserver *Observer) const { + MachineIRBuilder &Builder, const int64_t *MatchTable, + const TargetInstrInfo &TII, MachineRegisterInfo &MRI, + const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI, + const PredicateBitset &AvailableFeatures, + CodeGenCoverage *CoverageInfo) const { + + // Setup observer + GIMatchTableObserver MTObserver; + GISelObserverWrapper Observer(&MTObserver); + if (auto *CurObs = Builder.getChangeObserver()) + Observer.addObserver(CurObs); + + // TODO: Set MF delegate? + + // Setup builder. + auto RestoreOldObserver = Builder.setTemporaryChangeObserver(Observer); uint64_t CurrentIdx = 0; SmallVector OnFailResumeAt; + // We also record MachineInstrs manually in this vector so opcodes can address + // them. + SmallVector OutMIs; + // Bypass the flag check on the instruction, and only look at the MCInstrDesc. bool NoFPException = !State.MIs[0]->getDesc().mayRaiseFPException(); @@ -71,14 +88,16 @@ bool GIMatchTableExecutor::executeMatchTable( return RejectAndResume; }; - auto propagateFlags = [=](NewMIVector &OutMIs) { - for (auto MIB : OutMIs) { + auto propagateFlags = [&]() { + for (auto *MI : MTObserver.CreatedInsts) { // Set the NoFPExcept flag when no original matched instruction could // raise an FP exception, but the new instruction potentially might. uint16_t MIBFlags = Flags; - if (NoFPException && MIB->mayRaiseFPException()) + if (NoFPException && MI->mayRaiseFPException()) MIBFlags |= MachineInstr::NoFPExcept; - MIB.setMIFlags(MIBFlags); + Observer.changingInstr(*MI); + MI->setFlags(MIBFlags); + Observer.changedInstr(*MI); } return true; @@ -901,6 +920,7 @@ bool GIMatchTableExecutor::executeMatchTable( OutMIs[NewInsnID] = MachineInstrBuilder(*State.MIs[OldInsnID]->getMF(), State.MIs[OldInsnID]); OutMIs[NewInsnID]->setDesc(TII.get(NewOpcode)); + MTObserver.CreatedInsts.insert(OutMIs[NewInsnID]); DEBUG_WITH_TYPE(TgtExecutor::getName(), dbgs() << CurrentIdx << ": GIR_MutateOpcode(OutMIs[" << NewInsnID << "], MIs[" << OldInsnID << "], " @@ -914,14 +934,23 @@ bool GIMatchTableExecutor::executeMatchTable( if (NewInsnID >= OutMIs.size()) OutMIs.resize(NewInsnID + 1); - OutMIs[NewInsnID] = BuildMI(*State.MIs[0]->getParent(), State.MIs[0], - MIMetadata(*State.MIs[0]), TII.get(Opcode)); + OutMIs[NewInsnID] = Builder.buildInstr(Opcode); DEBUG_WITH_TYPE(TgtExecutor::getName(), dbgs() << CurrentIdx << ": GIR_BuildMI(OutMIs[" << NewInsnID << "], " << Opcode << ")\n"); break; } + case GIR_BuildConstant: { + int64_t TempRegID = MatchTable[CurrentIdx++]; + int64_t Imm = MatchTable[CurrentIdx++]; + Builder.buildConstant(State.TempRegisters[TempRegID], Imm); + DEBUG_WITH_TYPE(TgtExecutor::getName(), + dbgs() << CurrentIdx << ": GIR_BuildConstant(TempReg[" + << TempRegID << "], Imm=" << Imm << ")\n"); + break; + } + case GIR_Copy: { int64_t NewInsnID = MatchTable[CurrentIdx++]; int64_t OldInsnID = MatchTable[CurrentIdx++]; @@ -1239,8 +1268,11 @@ bool GIMatchTableExecutor::executeMatchTable( DEBUG_WITH_TYPE(TgtExecutor::getName(), dbgs() << CurrentIdx << ": GIR_EraseFromParent(MIs[" << InsnID << "])\n"); - if (Observer) - Observer->erasingInstr(*MI); + // If we're erasing the insertion point, ensure we don't leave a dangling + // pointer in the builder. + if (Builder.getInsertPt() == MI) + Builder.setInsertPt(*MI->getParent(), ++MI->getIterator()); + Observer.erasingInstr(*MI); MI->eraseFromParent(); break; } @@ -1269,11 +1301,9 @@ bool GIMatchTableExecutor::executeMatchTable( Register Old = State.MIs[OldInsnID]->getOperand(OldOpIdx).getReg(); Register New = State.MIs[NewInsnID]->getOperand(NewOpIdx).getReg(); - if (Observer) - Observer->changingAllUsesOfReg(MRI, Old); + Observer.changingAllUsesOfReg(MRI, Old); MRI.replaceRegWith(Old, New); - if (Observer) - Observer->finishedChangingAllUsesOfReg(); + Observer.finishedChangingAllUsesOfReg(); break; } case GIR_ReplaceRegWithTempReg: { @@ -1288,11 +1318,9 @@ bool GIMatchTableExecutor::executeMatchTable( Register Old = State.MIs[OldInsnID]->getOperand(OldOpIdx).getReg(); Register New = State.TempRegisters[TempRegID]; - if (Observer) - Observer->changingAllUsesOfReg(MRI, Old); + Observer.changingAllUsesOfReg(MRI, Old); MRI.replaceRegWith(Old, New); - if (Observer) - Observer->finishedChangingAllUsesOfReg(); + Observer.finishedChangingAllUsesOfReg(); break; } case GIR_Coverage: { @@ -1309,11 +1337,7 @@ bool GIMatchTableExecutor::executeMatchTable( case GIR_Done: DEBUG_WITH_TYPE(TgtExecutor::getName(), dbgs() << CurrentIdx << ": GIR_Done\n"); - if (Observer) { - for (MachineInstr *MI : OutMIs) - Observer->createdInstr(*MI); - } - propagateFlags(OutMIs); + propagateFlags(); return true; default: llvm_unreachable("Unexpected command"); diff --git a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h index e7db9547f03b694..99b821406b0f893 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h @@ -20,6 +20,7 @@ #include "llvm/CodeGen/TargetOpcodes.h" #include "llvm/IR/DebugLoc.h" #include "llvm/IR/Module.h" +#include "llvm/Support/SaveAndRestore.h" namespace llvm { @@ -364,6 +365,15 @@ class MachineIRBuilder { State.Observer = &Observer; } + GISelChangeObserver *getChangeObserver() const { return State.Observer; } + + // Replaces the change observer with \p Observer and returns an object that + // restores the old Observer on destruction. + SaveAndRestore + setTemporaryChangeObserver(GISelChangeObserver &Observer) { + return SaveAndRestore(State.Observer, &Observer); + } + void stopObservingChanges() { State.Observer = nullptr; } bool isObservingChanges() const { return State.Observer != nullptr; } diff --git a/llvm/lib/CodeGen/GlobalISel/GIMatchTableExecutor.cpp b/llvm/lib/CodeGen/GlobalISel/GIMatchTableExecutor.cpp index 26752369a7711a1..c1ababb8ed852d0 100644 --- a/llvm/lib/CodeGen/GlobalISel/GIMatchTableExecutor.cpp +++ b/llvm/lib/CodeGen/GlobalISel/GIMatchTableExecutor.cpp @@ -21,6 +21,10 @@ using namespace llvm; +GIMatchTableExecutor::GIMatchTableObserver::~GIMatchTableObserver() { + // anchor +} + GIMatchTableExecutor::MatcherState::MatcherState(unsigned MaxRenderers) : Renderers(MaxRenderers) {} diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-sdiv.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-sdiv.mir index e99ee84100a3991..13f9998952e6ed3 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-sdiv.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-sdiv.mir @@ -22,10 +22,10 @@ body: | ; CHECK: liveins: $w0 ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 - ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 3 - ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 -991146299 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = exact G_CONSTANT i32 3 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = exact G_CONSTANT i32 -991146299 ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(s32) = exact G_ASHR [[COPY]], [[C]](s32) - ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[ASHR]], [[C1]] + ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = exact G_MUL [[ASHR]], [[C1]] ; CHECK-NEXT: $w0 = COPY [[MUL]](s32) ; CHECK-NEXT: RET_ReallyLR implicit $w0 %0:_(s32) = COPY $w0 @@ -87,13 +87,13 @@ body: | ; CHECK: liveins: $q0 ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<4 x s32>) = COPY $q0 - ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 3 - ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 -991146299 - ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 954437177 - ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C]](s32), [[C]](s32), [[C]](s32), [[C]](s32) - ; CHECK-NEXT: [[BUILD_VECTOR1:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C1]](s32), [[C2]](s32), [[C1]](s32), [[C2]](s32) + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = exact G_CONSTANT i32 3 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = exact G_CONSTANT i32 -991146299 + ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = exact G_CONSTANT i32 954437177 + ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s32>) = exact G_BUILD_VECTOR [[C]](s32), [[C]](s32), [[C]](s32), [[C]](s32) + ; CHECK-NEXT: [[BUILD_VECTOR1:%[0-9]+]]:_(<4 x s32>) = exact G_BUILD_VECTOR [[C1]](s32), [[C2]](s32), [[C1]](s32), [[C2]](s32) ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(<4 x s32>) = exact G_ASHR [[COPY]], [[BUILD_VECTOR]](<4 x s32>) - ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(<4 x s32>) = G_MUL [[ASHR]], [[BUILD_VECTOR1]] + ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(<4 x s32>) = exact G_MUL [[ASHR]], [[BUILD_VECTOR1]] ; CHECK-NEXT: $q0 = COPY [[MUL]](<4 x s32>) ; CHECK-NEXT: RET_ReallyLR implicit $q0 %0:_(<4 x s32>) = COPY $q0 @@ -115,12 +115,12 @@ body: | ; CHECK: liveins: $q0 ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<4 x s32>) = COPY $q0 - ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 3 - ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 -991146299 - ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C]](s32), [[C]](s32), [[C]](s32), [[C]](s32) - ; CHECK-NEXT: [[BUILD_VECTOR1:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C1]](s32), [[C1]](s32), [[C1]](s32), [[C1]](s32) + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = exact G_CONSTANT i32 3 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = exact G_CONSTANT i32 -991146299 + ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s32>) = exact G_BUILD_VECTOR [[C]](s32), [[C]](s32), [[C]](s32), [[C]](s32) + ; CHECK-NEXT: [[BUILD_VECTOR1:%[0-9]+]]:_(<4 x s32>) = exact G_BUILD_VECTOR [[C1]](s32), [[C1]](s32), [[C1]](s32), [[C1]](s32) ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(<4 x s32>) = exact G_ASHR [[COPY]], [[BUILD_VECTOR]](<4 x s32>) - ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(<4 x s32>) = G_MUL [[ASHR]], [[BUILD_VECTOR1]] + ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(<4 x s32>) = exact G_MUL [[ASHR]], [[BUILD_VECTOR1]] ; CHECK-NEXT: $q0 = COPY [[MUL]](<4 x s32>) ; CHECK-NEXT: RET_ReallyLR implicit $q0 %0:_(<4 x s32>) = COPY $q0 diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizercombiner-ashr-shl-to-sext-inreg.mir b/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizercombiner-ashr-shl-to-sext-inreg.mir index 9e540390dd37f43..9176328d873e619 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizercombiner-ashr-shl-to-sext-inreg.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizercombiner-ashr-shl-to-sext-inreg.mir @@ -15,7 +15,7 @@ body: | ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) - ; CHECK-NEXT: [[SEXT_INREG:%[0-9]+]]:_(s16) = G_SEXT_INREG [[TRUNC]], 8 + ; CHECK-NEXT: [[SEXT_INREG:%[0-9]+]]:_(s16) = exact G_SEXT_INREG [[TRUNC]], 8 ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[SEXT_INREG]](s16) ; CHECK-NEXT: $w0 = COPY [[ANYEXT]](s32) ; CHECK-NEXT: RET_ReallyLR implicit $w0 @@ -75,7 +75,7 @@ body: | ; CHECK: liveins: $d0 ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $d0 - ; CHECK-NEXT: [[SEXT_INREG:%[0-9]+]]:_(<4 x s16>) = G_SEXT_INREG [[COPY]], 8 + ; CHECK-NEXT: [[SEXT_INREG:%[0-9]+]]:_(<4 x s16>) = exact G_SEXT_INREG [[COPY]], 8 ; CHECK-NEXT: $d0 = COPY [[SEXT_INREG]](<4 x s16>) ; CHECK-NEXT: RET_ReallyLR implicit $d0 %0:_(<4 x s16>) = COPY $d0 diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/combine-fma-add-mul-pre-legalize.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/combine-fma-add-mul-pre-legalize.mir index ee775dc674cfecd..90df73e85c9e7c7 100644 --- a/llvm/test/Cod... |
@llvm/pr-subscribers-backend-amdgpu ChangesNOTE: This is part of a stack. Please only review the last commit, see #65955 to review the first commit. Use -- Patch is 97.20 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/66077.diff 21 Files Affected:
diff --git a/llvm/docs/GlobalISel/MIRPatterns.rst b/llvm/docs/GlobalISel/MIRPatterns.rst index 51d1850a1236039..fa70311f48572de 100644 --- a/llvm/docs/GlobalISel/MIRPatterns.rst +++ b/llvm/docs/GlobalISel/MIRPatterns.rst @@ -257,8 +257,8 @@ Common Pattern #3: Emitting a Constant Value When an immediate operand appears in an 'apply' pattern, the behavior depends on whether it's typed or not. -* If the immediate is typed, a ``G_CONSTANT`` is implicitly emitted - (= a register operand is added to the instruction). +* If the immediate is typed, ``MachineIRBuilder::buildConstant`` is used + to create a ``G_CONSTANT``. A ``G_BUILD_VECTOR`` will be used for vectors. * If the immediate is untyped, a simple immediate is added (``MachineInstrBuilder::addImm``). diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h index 2b0733cf9353e6c..89c0b097281ddfa 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h @@ -18,6 +18,7 @@ #include "llvm/ADT/Bitset.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h" #include "llvm/CodeGen/GlobalISel/Utils.h" #include "llvm/CodeGen/LowLevelType.h" #include "llvm/CodeGen/MachineFunction.h" @@ -40,6 +41,7 @@ class APInt; class APFloat; class GISelKnownBits; class MachineInstr; +class MachineIRBuilder; class MachineInstrBuilder; class MachineFunction; class MachineOperand; @@ -291,6 +293,11 @@ enum { /// - Opcode - The new opcode to use GIR_BuildMI, + /// Builds a constant and stores its result in a TempReg. + /// - TempRegID - Temp Register to define. + /// - Imm - The immediate to add + GIR_BuildConstant, + /// Copy an operand to the specified instruction /// - NewInsnID - Instruction ID to modify /// - OldInsnID - Instruction ID to copy from @@ -501,10 +508,25 @@ class GIMatchTableExecutor { } protected: + /// Observer used by \ref executeMatchTable to record all instructions created + /// by the rule. + class GIMatchTableObserver : public GISelChangeObserver { + public: + virtual ~GIMatchTableObserver(); + + void erasingInstr(MachineInstr &MI) override { CreatedInsts.erase(&MI); } + void createdInstr(MachineInstr &MI) override { CreatedInsts.insert(&MI); } + void changingInstr(MachineInstr &MI) override {} + void changedInstr(MachineInstr &MI) override {} + + // Keeps track of all instructions that have been created when applying a + // rule. + SmallDenseSet CreatedInsts; + }; + using ComplexRendererFns = std::optional, 4>>; using RecordedMIVector = SmallVector; - using NewMIVector = SmallVector; struct MatcherState { std::vector Renderers; @@ -555,15 +577,15 @@ class GIMatchTableExecutor { /// and false otherwise. template - bool executeMatchTable( - TgtExecutor &Exec, NewMIVector &OutMIs, MatcherState &State, - const ExecInfoTy - &ISelInfo, - const int64_t *MatchTable, const TargetInstrInfo &TII, - MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, - const RegisterBankInfo &RBI, const PredicateBitset &AvailableFeatures, - CodeGenCoverage *CoverageInfo, - GISelChangeObserver *Observer = nullptr) const; + bool executeMatchTable(TgtExecutor &Exec, MatcherState &State, + const ExecInfoTy &ExecInfo, + MachineIRBuilder &Builder, const int64_t *MatchTable, + const TargetInstrInfo &TII, MachineRegisterInfo &MRI, + const TargetRegisterInfo &TRI, + const RegisterBankInfo &RBI, + const PredicateBitset &AvailableFeatures, + CodeGenCoverage *CoverageInfo) const; virtual const int64_t *getMatchTable() const { llvm_unreachable("Should have been overridden by tablegen if used"); @@ -592,7 +614,7 @@ class GIMatchTableExecutor { } virtual void runCustomAction(unsigned, const MatcherState &State, - NewMIVector &OutMIs) const { + ArrayRef OutMIs) const { llvm_unreachable("Subclass does not implement runCustomAction!"); } diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h index 883c1ca0fe350b0..92a1eb561fb10ae 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h @@ -18,6 +18,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h" #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h" +#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" #include "llvm/CodeGen/GlobalISel/Utils.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineOperand.h" @@ -42,17 +43,33 @@ namespace llvm { template bool GIMatchTableExecutor::executeMatchTable( - TgtExecutor &Exec, NewMIVector &OutMIs, MatcherState &State, + TgtExecutor &Exec, MatcherState &State, const ExecInfoTy &ExecInfo, - const int64_t *MatchTable, const TargetInstrInfo &TII, - MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, - const RegisterBankInfo &RBI, const PredicateBitset &AvailableFeatures, - CodeGenCoverage *CoverageInfo, GISelChangeObserver *Observer) const { + MachineIRBuilder &Builder, const int64_t *MatchTable, + const TargetInstrInfo &TII, MachineRegisterInfo &MRI, + const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI, + const PredicateBitset &AvailableFeatures, + CodeGenCoverage *CoverageInfo) const { + + // Setup observer + GIMatchTableObserver MTObserver; + GISelObserverWrapper Observer(&MTObserver); + if (auto *CurObs = Builder.getChangeObserver()) + Observer.addObserver(CurObs); + + // TODO: Set MF delegate? + + // Setup builder. + auto RestoreOldObserver = Builder.setTemporaryChangeObserver(Observer); uint64_t CurrentIdx = 0; SmallVector OnFailResumeAt; + // We also record MachineInstrs manually in this vector so opcodes can address + // them. + SmallVector OutMIs; + // Bypass the flag check on the instruction, and only look at the MCInstrDesc. bool NoFPException = !State.MIs[0]->getDesc().mayRaiseFPException(); @@ -71,14 +88,16 @@ bool GIMatchTableExecutor::executeMatchTable( return RejectAndResume; }; - auto propagateFlags = [=](NewMIVector &OutMIs) { - for (auto MIB : OutMIs) { + auto propagateFlags = [&]() { + for (auto *MI : MTObserver.CreatedInsts) { // Set the NoFPExcept flag when no original matched instruction could // raise an FP exception, but the new instruction potentially might. uint16_t MIBFlags = Flags; - if (NoFPException && MIB->mayRaiseFPException()) + if (NoFPException && MI->mayRaiseFPException()) MIBFlags |= MachineInstr::NoFPExcept; - MIB.setMIFlags(MIBFlags); + Observer.changingInstr(*MI); + MI->setFlags(MIBFlags); + Observer.changedInstr(*MI); } return true; @@ -901,6 +920,7 @@ bool GIMatchTableExecutor::executeMatchTable( OutMIs[NewInsnID] = MachineInstrBuilder(*State.MIs[OldInsnID]->getMF(), State.MIs[OldInsnID]); OutMIs[NewInsnID]->setDesc(TII.get(NewOpcode)); + MTObserver.CreatedInsts.insert(OutMIs[NewInsnID]); DEBUG_WITH_TYPE(TgtExecutor::getName(), dbgs() << CurrentIdx << ": GIR_MutateOpcode(OutMIs[" << NewInsnID << "], MIs[" << OldInsnID << "], " @@ -914,14 +934,23 @@ bool GIMatchTableExecutor::executeMatchTable( if (NewInsnID >= OutMIs.size()) OutMIs.resize(NewInsnID + 1); - OutMIs[NewInsnID] = BuildMI(*State.MIs[0]->getParent(), State.MIs[0], - MIMetadata(*State.MIs[0]), TII.get(Opcode)); + OutMIs[NewInsnID] = Builder.buildInstr(Opcode); DEBUG_WITH_TYPE(TgtExecutor::getName(), dbgs() << CurrentIdx << ": GIR_BuildMI(OutMIs[" << NewInsnID << "], " << Opcode << ")\n"); break; } + case GIR_BuildConstant: { + int64_t TempRegID = MatchTable[CurrentIdx++]; + int64_t Imm = MatchTable[CurrentIdx++]; + Builder.buildConstant(State.TempRegisters[TempRegID], Imm); + DEBUG_WITH_TYPE(TgtExecutor::getName(), + dbgs() << CurrentIdx << ": GIR_BuildConstant(TempReg[" + << TempRegID << "], Imm=" << Imm << ")\n"); + break; + } + case GIR_Copy: { int64_t NewInsnID = MatchTable[CurrentIdx++]; int64_t OldInsnID = MatchTable[CurrentIdx++]; @@ -1239,8 +1268,11 @@ bool GIMatchTableExecutor::executeMatchTable( DEBUG_WITH_TYPE(TgtExecutor::getName(), dbgs() << CurrentIdx << ": GIR_EraseFromParent(MIs[" << InsnID << "])\n"); - if (Observer) - Observer->erasingInstr(*MI); + // If we're erasing the insertion point, ensure we don't leave a dangling + // pointer in the builder. + if (Builder.getInsertPt() == MI) + Builder.setInsertPt(*MI->getParent(), ++MI->getIterator()); + Observer.erasingInstr(*MI); MI->eraseFromParent(); break; } @@ -1269,11 +1301,9 @@ bool GIMatchTableExecutor::executeMatchTable( Register Old = State.MIs[OldInsnID]->getOperand(OldOpIdx).getReg(); Register New = State.MIs[NewInsnID]->getOperand(NewOpIdx).getReg(); - if (Observer) - Observer->changingAllUsesOfReg(MRI, Old); + Observer.changingAllUsesOfReg(MRI, Old); MRI.replaceRegWith(Old, New); - if (Observer) - Observer->finishedChangingAllUsesOfReg(); + Observer.finishedChangingAllUsesOfReg(); break; } case GIR_ReplaceRegWithTempReg: { @@ -1288,11 +1318,9 @@ bool GIMatchTableExecutor::executeMatchTable( Register Old = State.MIs[OldInsnID]->getOperand(OldOpIdx).getReg(); Register New = State.TempRegisters[TempRegID]; - if (Observer) - Observer->changingAllUsesOfReg(MRI, Old); + Observer.changingAllUsesOfReg(MRI, Old); MRI.replaceRegWith(Old, New); - if (Observer) - Observer->finishedChangingAllUsesOfReg(); + Observer.finishedChangingAllUsesOfReg(); break; } case GIR_Coverage: { @@ -1309,11 +1337,7 @@ bool GIMatchTableExecutor::executeMatchTable( case GIR_Done: DEBUG_WITH_TYPE(TgtExecutor::getName(), dbgs() << CurrentIdx << ": GIR_Done\n"); - if (Observer) { - for (MachineInstr *MI : OutMIs) - Observer->createdInstr(*MI); - } - propagateFlags(OutMIs); + propagateFlags(); return true; default: llvm_unreachable("Unexpected command"); diff --git a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h index e7db9547f03b694..99b821406b0f893 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h @@ -20,6 +20,7 @@ #include "llvm/CodeGen/TargetOpcodes.h" #include "llvm/IR/DebugLoc.h" #include "llvm/IR/Module.h" +#include "llvm/Support/SaveAndRestore.h" namespace llvm { @@ -364,6 +365,15 @@ class MachineIRBuilder { State.Observer = &Observer; } + GISelChangeObserver *getChangeObserver() const { return State.Observer; } + + // Replaces the change observer with \p Observer and returns an object that + // restores the old Observer on destruction. + SaveAndRestore + setTemporaryChangeObserver(GISelChangeObserver &Observer) { + return SaveAndRestore(State.Observer, &Observer); + } + void stopObservingChanges() { State.Observer = nullptr; } bool isObservingChanges() const { return State.Observer != nullptr; } diff --git a/llvm/lib/CodeGen/GlobalISel/GIMatchTableExecutor.cpp b/llvm/lib/CodeGen/GlobalISel/GIMatchTableExecutor.cpp index 26752369a7711a1..c1ababb8ed852d0 100644 --- a/llvm/lib/CodeGen/GlobalISel/GIMatchTableExecutor.cpp +++ b/llvm/lib/CodeGen/GlobalISel/GIMatchTableExecutor.cpp @@ -21,6 +21,10 @@ using namespace llvm; +GIMatchTableExecutor::GIMatchTableObserver::~GIMatchTableObserver() { + // anchor +} + GIMatchTableExecutor::MatcherState::MatcherState(unsigned MaxRenderers) : Renderers(MaxRenderers) {} diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-sdiv.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-sdiv.mir index e99ee84100a3991..13f9998952e6ed3 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-sdiv.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-sdiv.mir @@ -22,10 +22,10 @@ body: | ; CHECK: liveins: $w0 ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 - ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 3 - ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 -991146299 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = exact G_CONSTANT i32 3 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = exact G_CONSTANT i32 -991146299 ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(s32) = exact G_ASHR [[COPY]], [[C]](s32) - ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[ASHR]], [[C1]] + ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = exact G_MUL [[ASHR]], [[C1]] ; CHECK-NEXT: $w0 = COPY [[MUL]](s32) ; CHECK-NEXT: RET_ReallyLR implicit $w0 %0:_(s32) = COPY $w0 @@ -87,13 +87,13 @@ body: | ; CHECK: liveins: $q0 ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<4 x s32>) = COPY $q0 - ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 3 - ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 -991146299 - ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 954437177 - ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C]](s32), [[C]](s32), [[C]](s32), [[C]](s32) - ; CHECK-NEXT: [[BUILD_VECTOR1:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C1]](s32), [[C2]](s32), [[C1]](s32), [[C2]](s32) + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = exact G_CONSTANT i32 3 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = exact G_CONSTANT i32 -991146299 + ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = exact G_CONSTANT i32 954437177 + ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s32>) = exact G_BUILD_VECTOR [[C]](s32), [[C]](s32), [[C]](s32), [[C]](s32) + ; CHECK-NEXT: [[BUILD_VECTOR1:%[0-9]+]]:_(<4 x s32>) = exact G_BUILD_VECTOR [[C1]](s32), [[C2]](s32), [[C1]](s32), [[C2]](s32) ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(<4 x s32>) = exact G_ASHR [[COPY]], [[BUILD_VECTOR]](<4 x s32>) - ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(<4 x s32>) = G_MUL [[ASHR]], [[BUILD_VECTOR1]] + ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(<4 x s32>) = exact G_MUL [[ASHR]], [[BUILD_VECTOR1]] ; CHECK-NEXT: $q0 = COPY [[MUL]](<4 x s32>) ; CHECK-NEXT: RET_ReallyLR implicit $q0 %0:_(<4 x s32>) = COPY $q0 @@ -115,12 +115,12 @@ body: | ; CHECK: liveins: $q0 ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<4 x s32>) = COPY $q0 - ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 3 - ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 -991146299 - ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C]](s32), [[C]](s32), [[C]](s32), [[C]](s32) - ; CHECK-NEXT: [[BUILD_VECTOR1:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C1]](s32), [[C1]](s32), [[C1]](s32), [[C1]](s32) + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = exact G_CONSTANT i32 3 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = exact G_CONSTANT i32 -991146299 + ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s32>) = exact G_BUILD_VECTOR [[C]](s32), [[C]](s32), [[C]](s32), [[C]](s32) + ; CHECK-NEXT: [[BUILD_VECTOR1:%[0-9]+]]:_(<4 x s32>) = exact G_BUILD_VECTOR [[C1]](s32), [[C1]](s32), [[C1]](s32), [[C1]](s32) ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(<4 x s32>) = exact G_ASHR [[COPY]], [[BUILD_VECTOR]](<4 x s32>) - ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(<4 x s32>) = G_MUL [[ASHR]], [[BUILD_VECTOR1]] + ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(<4 x s32>) = exact G_MUL [[ASHR]], [[BUILD_VECTOR1]] ; CHECK-NEXT: $q0 = COPY [[MUL]](<4 x s32>) ; CHECK-NEXT: RET_ReallyLR implicit $q0 %0:_(<4 x s32>) = COPY $q0 diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizercombiner-ashr-shl-to-sext-inreg.mir b/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizercombiner-ashr-shl-to-sext-inreg.mir index 9e540390dd37f43..9176328d873e619 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizercombiner-ashr-shl-to-sext-inreg.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizercombiner-ashr-shl-to-sext-inreg.mir @@ -15,7 +15,7 @@ body: | ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) - ; CHECK-NEXT: [[SEXT_INREG:%[0-9]+]]:_(s16) = G_SEXT_INREG [[TRUNC]], 8 + ; CHECK-NEXT: [[SEXT_INREG:%[0-9]+]]:_(s16) = exact G_SEXT_INREG [[TRUNC]], 8 ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[SEXT_INREG]](s16) ; CHECK-NEXT: $w0 = COPY [[ANYEXT]](s32) ; CHECK-NEXT: RET_ReallyLR implicit $w0 @@ -75,7 +75,7 @@ body: | ; CHECK: liveins: $d0 ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $d0 - ; CHECK-NEXT: [[SEXT_INREG:%[0-9]+]]:_(<4 x s16>) = G_SEXT_INREG [[COPY]], 8 + ; CHECK-NEXT: [[SEXT_INREG:%[0-9]+]]:_(<4 x s16>) = exact G_SEXT_INREG [[COPY]], 8 ; CHECK-NEXT: $d0 = COPY [[SEXT_INREG]](<4 x s16>) ; CHECK-NEXT: RET_ReallyLR implicit $d0 %0:_(<4 x s16>) = COPY $d0 diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/combine-fma-add-mul-pre-legalize.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/combine-fma-add-mul-pre-legalize.mir index ee775dc674cfecd..90df73e85c9e7c7 100644 --- a/llvm/test/Cod... |
ping |
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
0fa6436
to
048d0e5
Compare
Do you have any follow ups that would take advantage of that? |
I got a couple more patches in this stack, there is an example in #66079 which isn't possible without this |
NOTE: This is part of a stack. Please only review the last commit, see #65955 to review the first commit.
Use
MachineIRBuilder::buildConstant
to emit typed immediates in 'apply' MIR patterns.This adds flexibility, e.g. it allows us to seamlessly handle vector cases, where a
G_BUILD_VECTOR
is needed to create a splat.