diff --git a/llvm/docs/GlobalISel/MIRPatterns.rst b/llvm/docs/GlobalISel/MIRPatterns.rst index 51d1850a12360..fa70311f48572 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 2b0733cf9353e..1af12e1017c34 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; @@ -274,6 +276,12 @@ enum { /// - StoreIdx - Store location in RecordedOperands. GIM_RecordNamedOperand, + /// TODO DESC + /// - InsnID - Instruction ID + /// - OpIdx - Operand index + /// - TempTypeIdx - Temp Type Index, always negative. + GIM_RecordRegType, + /// Fail the current try-block, or completely fail to match if there is no /// current try-block. GIM_Reject, @@ -291,6 +299,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 @@ -350,12 +363,6 @@ enum { /// - Imm - The immediate to add GIR_AddImm, - /// Add an CImm to the specified instruction - /// - InsnID - Instruction ID to modify - /// - Ty - Type of the constant immediate. - /// - Imm - The immediate to add - GIR_AddCImm, - /// Render complex operands to the specified instruction /// - InsnID - Instruction ID to modify /// - RendererID - The renderer to call @@ -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; @@ -516,6 +538,10 @@ class GIMatchTableExecutor { /// list. Currently such predicates don't have more then 3 arguments. std::array RecordedOperands; + /// Types extracted from an instruction's operand. + /// Whenever a type index is negative, we look here instead. + SmallVector RecordedTypes; + MatcherState(unsigned MaxRenderers); }; @@ -555,15 +581,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 +618,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 883c1ca0fe350..fa8bddf795a9a 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,19 +88,29 @@ 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; }; + // If the index is >= 0, it's an index in the type objects generated by TableGen. + // If the index is <0, it's an index in the recorded types object. + auto getTypeFromIdx = [&](int64_t Idx) -> const LLT& { + if(Idx >= 0) + return ExecInfo.TypeObjects[Idx]; + return State.RecordedTypes[1 - Idx]; + }; + while (true) { assert(CurrentIdx != ~0u && "Invalid MatchTable index"); int64_t MatcherOpcode = MatchTable[CurrentIdx++]; @@ -620,7 +647,7 @@ bool GIMatchTableExecutor::executeMatchTable( assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx); if (!MO.isReg() || - MRI.getType(MO.getReg()) != ExecInfo.TypeObjects[TypeID]) { + MRI.getType(MO.getReg()) != getTypeFromIdx(TypeID)) { if (handleReject() == RejectAndGiveUp) return false; } @@ -671,6 +698,25 @@ bool GIMatchTableExecutor::executeMatchTable( State.RecordedOperands[StoreIdx] = &State.MIs[InsnID]->getOperand(OpIdx); break; } + case GIM_RecordRegType: { + int64_t InsnID = MatchTable[CurrentIdx++]; + int64_t OpIdx = MatchTable[CurrentIdx++]; + int64_t TypeIdx = MatchTable[CurrentIdx++]; + + DEBUG_WITH_TYPE(TgtExecutor::getName(), + dbgs() << CurrentIdx << ": GIM_RecordRegType(MIs[" + << InsnID << "]->getOperand(" << OpIdx + << "), TypeIdx=" << TypeIdx << ")\n"); + assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); + assert(TypeIdx <= 0 && "Temp types always have negative indexes!"); + // Indexes start at -1. + TypeIdx = 1 - TypeIdx; + const auto& Op = State.MIs[InsnID]->getOperand(OpIdx); + if(State.RecordedTypes.size() <= (uint64_t)TypeIdx) + State.RecordedTypes.resize(TypeIdx + 1, LLT()); + State.RecordedTypes[TypeIdx] = MRI.getType(Op.getReg()); + break; + } case GIM_CheckRegBankForClass: { int64_t InsnID = MatchTable[CurrentIdx++]; int64_t OpIdx = MatchTable[CurrentIdx++]; @@ -901,6 +947,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 +961,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++]; @@ -1047,24 +1103,6 @@ bool GIMatchTableExecutor::executeMatchTable( << "], " << Imm << ")\n"); break; } - - case GIR_AddCImm: { - int64_t InsnID = MatchTable[CurrentIdx++]; - int64_t TypeID = MatchTable[CurrentIdx++]; - int64_t Imm = MatchTable[CurrentIdx++]; - assert(OutMIs[InsnID] && "Attempted to add to undefined instruction"); - - unsigned Width = ExecInfo.TypeObjects[TypeID].getScalarSizeInBits(); - LLVMContext &Ctx = MF->getFunction().getContext(); - OutMIs[InsnID].addCImm( - ConstantInt::get(IntegerType::get(Ctx, Width), Imm, /*signed*/ true)); - DEBUG_WITH_TYPE(TgtExecutor::getName(), - dbgs() << CurrentIdx << ": GIR_AddCImm(OutMIs[" << InsnID - << "], TypeID=" << TypeID << ", Imm=" << Imm - << ")\n"); - break; - } - case GIR_ComplexRenderer: { int64_t InsnID = MatchTable[CurrentIdx++]; int64_t RendererID = MatchTable[CurrentIdx++]; @@ -1239,8 +1277,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; } @@ -1250,7 +1291,7 @@ bool GIMatchTableExecutor::executeMatchTable( int64_t TypeID = MatchTable[CurrentIdx++]; State.TempRegisters[TempRegID] = - MRI.createGenericVirtualRegister(ExecInfo.TypeObjects[TypeID]); + MRI.createGenericVirtualRegister(getTypeFromIdx(TypeID)); DEBUG_WITH_TYPE(TgtExecutor::getName(), dbgs() << CurrentIdx << ": TempRegs[" << TempRegID << "] = GIR_MakeTempReg(" << TypeID << ")\n"); @@ -1269,11 +1310,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 +1327,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 +1346,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 e7db9547f03b6..99b821406b0f8 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/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td index 7e0691e1ee950..4a22dd61c6e9b 100644 --- a/llvm/include/llvm/Target/GlobalISel/Combine.td +++ b/llvm/include/llvm/Target/GlobalISel/Combine.td @@ -110,6 +110,24 @@ class GICombinePatFrag alts> { list Alternatives = alts; } +//===----------------------------------------------------------------------===// +// Pattern Special Types +//===----------------------------------------------------------------------===// + +class GISpecialType; + +// In an apply pattern, GITypeOf can be used to set the type of a new temporary +// register to match the type of a matched register. +// +// This can only be used on temporary registers defined by the apply pattern. +// +// TODO: Make this work in matchers as well? +// +// FIXME: Syntax is very ugly. +class GITypeOf : GISpecialType { + string OpName = opName; +} + //===----------------------------------------------------------------------===// // Pattern Builtins //===----------------------------------------------------------------------===// diff --git a/llvm/lib/CodeGen/GlobalISel/GIMatchTableExecutor.cpp b/llvm/lib/CodeGen/GlobalISel/GIMatchTableExecutor.cpp index 26752369a7711..c1ababb8ed852 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 e99ee84100a39..13f9998952e6e 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 9e540390dd37f..9176328d873e6 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 ee775dc674cfe..90df73e85c9e7 100644 --- 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 @@ -31,7 +31,7 @@ body: | ; GFX9-CONTRACT-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; GFX9-CONTRACT-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 ; GFX9-CONTRACT-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $vgpr2 - ; GFX9-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(s32) = G_FMA [[COPY]], [[COPY1]], [[COPY2]] + ; GFX9-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(s32) = reassoc G_FMA [[COPY]], [[COPY1]], [[COPY2]] ; GFX9-CONTRACT-NEXT: $vgpr0 = COPY [[FMA]](s32) ; GFX9-CONTRACT-NEXT: S_SETPC_B64_return $sgpr30_sgpr31, implicit $vgpr0 ; @@ -52,7 +52,7 @@ body: | ; GFX9-UNSAFE-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; GFX9-UNSAFE-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 ; GFX9-UNSAFE-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $vgpr2 - ; GFX9-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(s32) = G_FMA [[COPY]], [[COPY1]], [[COPY2]] + ; GFX9-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(s32) = reassoc G_FMA [[COPY]], [[COPY1]], [[COPY2]] ; GFX9-UNSAFE-NEXT: $vgpr0 = COPY [[FMA]](s32) ; GFX9-UNSAFE-NEXT: S_SETPC_B64_return $sgpr30_sgpr31, implicit $vgpr0 ; @@ -73,7 +73,7 @@ body: | ; GFX10-CONTRACT-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; GFX10-CONTRACT-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 ; GFX10-CONTRACT-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $vgpr2 - ; GFX10-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(s32) = G_FMA [[COPY]], [[COPY1]], [[COPY2]] + ; GFX10-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(s32) = reassoc G_FMA [[COPY]], [[COPY1]], [[COPY2]] ; GFX10-CONTRACT-NEXT: $vgpr0 = COPY [[FMA]](s32) ; GFX10-CONTRACT-NEXT: S_SETPC_B64_return $sgpr30_sgpr31, implicit $vgpr0 ; @@ -94,7 +94,7 @@ body: | ; GFX10-UNSAFE-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; GFX10-UNSAFE-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 ; GFX10-UNSAFE-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $vgpr2 - ; GFX10-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(s32) = G_FMA [[COPY]], [[COPY1]], [[COPY2]] + ; GFX10-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(s32) = reassoc G_FMA [[COPY]], [[COPY1]], [[COPY2]] ; GFX10-UNSAFE-NEXT: $vgpr0 = COPY [[FMA]](s32) ; GFX10-UNSAFE-NEXT: S_SETPC_B64_return $sgpr30_sgpr31, implicit $vgpr0 %0:_(s32) = COPY $vgpr0 @@ -129,7 +129,7 @@ body: | ; GFX9-CONTRACT-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; GFX9-CONTRACT-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 ; GFX9-CONTRACT-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $vgpr2 - ; GFX9-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(s32) = G_FMA [[COPY]], [[COPY1]], [[COPY2]] + ; GFX9-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(s32) = reassoc G_FMA [[COPY]], [[COPY1]], [[COPY2]] ; GFX9-CONTRACT-NEXT: $vgpr0 = COPY [[FMA]](s32) ; GFX9-CONTRACT-NEXT: S_SETPC_B64_return $sgpr30_sgpr31, implicit $vgpr0 ; @@ -150,7 +150,7 @@ body: | ; GFX9-UNSAFE-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; GFX9-UNSAFE-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 ; GFX9-UNSAFE-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $vgpr2 - ; GFX9-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(s32) = G_FMA [[COPY]], [[COPY1]], [[COPY2]] + ; GFX9-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(s32) = reassoc G_FMA [[COPY]], [[COPY1]], [[COPY2]] ; GFX9-UNSAFE-NEXT: $vgpr0 = COPY [[FMA]](s32) ; GFX9-UNSAFE-NEXT: S_SETPC_B64_return $sgpr30_sgpr31, implicit $vgpr0 ; @@ -171,7 +171,7 @@ body: | ; GFX10-CONTRACT-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; GFX10-CONTRACT-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 ; GFX10-CONTRACT-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $vgpr2 - ; GFX10-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(s32) = G_FMA [[COPY]], [[COPY1]], [[COPY2]] + ; GFX10-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(s32) = reassoc G_FMA [[COPY]], [[COPY1]], [[COPY2]] ; GFX10-CONTRACT-NEXT: $vgpr0 = COPY [[FMA]](s32) ; GFX10-CONTRACT-NEXT: S_SETPC_B64_return $sgpr30_sgpr31, implicit $vgpr0 ; @@ -192,7 +192,7 @@ body: | ; GFX10-UNSAFE-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; GFX10-UNSAFE-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 ; GFX10-UNSAFE-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $vgpr2 - ; GFX10-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(s32) = G_FMA [[COPY]], [[COPY1]], [[COPY2]] + ; GFX10-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(s32) = reassoc G_FMA [[COPY]], [[COPY1]], [[COPY2]] ; GFX10-UNSAFE-NEXT: $vgpr0 = COPY [[FMA]](s32) ; GFX10-UNSAFE-NEXT: S_SETPC_B64_return $sgpr30_sgpr31, implicit $vgpr0 %0:_(s32) = COPY $vgpr0 @@ -234,7 +234,7 @@ body: | ; GFX9-CONTRACT-NEXT: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) ; GFX9-CONTRACT-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $vgpr2 ; GFX9-CONTRACT-NEXT: [[TRUNC2:%[0-9]+]]:_(s16) = G_TRUNC [[COPY2]](s32) - ; GFX9-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(s16) = G_FMA [[TRUNC]], [[TRUNC1]], [[TRUNC2]] + ; GFX9-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(s16) = reassoc G_FMA [[TRUNC]], [[TRUNC1]], [[TRUNC2]] ; GFX9-CONTRACT-NEXT: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[FMA]](s16) ; GFX9-CONTRACT-NEXT: $vgpr0 = COPY [[ANYEXT]](s32) ; GFX9-CONTRACT-NEXT: S_SETPC_B64_return $sgpr30_sgpr31, implicit $vgpr0 @@ -263,7 +263,7 @@ body: | ; GFX9-UNSAFE-NEXT: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) ; GFX9-UNSAFE-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $vgpr2 ; GFX9-UNSAFE-NEXT: [[TRUNC2:%[0-9]+]]:_(s16) = G_TRUNC [[COPY2]](s32) - ; GFX9-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(s16) = G_FMA [[TRUNC]], [[TRUNC1]], [[TRUNC2]] + ; GFX9-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(s16) = reassoc G_FMA [[TRUNC]], [[TRUNC1]], [[TRUNC2]] ; GFX9-UNSAFE-NEXT: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[FMA]](s16) ; GFX9-UNSAFE-NEXT: $vgpr0 = COPY [[ANYEXT]](s32) ; GFX9-UNSAFE-NEXT: S_SETPC_B64_return $sgpr30_sgpr31, implicit $vgpr0 @@ -292,7 +292,7 @@ body: | ; GFX10-CONTRACT-NEXT: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) ; GFX10-CONTRACT-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $vgpr2 ; GFX10-CONTRACT-NEXT: [[TRUNC2:%[0-9]+]]:_(s16) = G_TRUNC [[COPY2]](s32) - ; GFX10-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(s16) = G_FMA [[TRUNC]], [[TRUNC1]], [[TRUNC2]] + ; GFX10-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(s16) = reassoc G_FMA [[TRUNC]], [[TRUNC1]], [[TRUNC2]] ; GFX10-CONTRACT-NEXT: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[FMA]](s16) ; GFX10-CONTRACT-NEXT: $vgpr0 = COPY [[ANYEXT]](s32) ; GFX10-CONTRACT-NEXT: S_SETPC_B64_return $sgpr30_sgpr31, implicit $vgpr0 @@ -321,7 +321,7 @@ body: | ; GFX10-UNSAFE-NEXT: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) ; GFX10-UNSAFE-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $vgpr2 ; GFX10-UNSAFE-NEXT: [[TRUNC2:%[0-9]+]]:_(s16) = G_TRUNC [[COPY2]](s32) - ; GFX10-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(s16) = G_FMA [[TRUNC]], [[TRUNC1]], [[TRUNC2]] + ; GFX10-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(s16) = reassoc G_FMA [[TRUNC]], [[TRUNC1]], [[TRUNC2]] ; GFX10-UNSAFE-NEXT: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[FMA]](s16) ; GFX10-UNSAFE-NEXT: $vgpr0 = COPY [[ANYEXT]](s32) ; GFX10-UNSAFE-NEXT: S_SETPC_B64_return $sgpr30_sgpr31, implicit $vgpr0 @@ -368,7 +368,7 @@ body: | ; GFX9-CONTRACT-NEXT: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) ; GFX9-CONTRACT-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $vgpr2 ; GFX9-CONTRACT-NEXT: [[TRUNC2:%[0-9]+]]:_(s16) = G_TRUNC [[COPY2]](s32) - ; GFX9-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(s16) = G_FMA [[TRUNC]], [[TRUNC1]], [[TRUNC2]] + ; GFX9-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(s16) = reassoc G_FMA [[TRUNC]], [[TRUNC1]], [[TRUNC2]] ; GFX9-CONTRACT-NEXT: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[FMA]](s16) ; GFX9-CONTRACT-NEXT: $vgpr0 = COPY [[ANYEXT]](s32) ; GFX9-CONTRACT-NEXT: S_SETPC_B64_return $sgpr30_sgpr31, implicit $vgpr0 @@ -397,7 +397,7 @@ body: | ; GFX9-UNSAFE-NEXT: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) ; GFX9-UNSAFE-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $vgpr2 ; GFX9-UNSAFE-NEXT: [[TRUNC2:%[0-9]+]]:_(s16) = G_TRUNC [[COPY2]](s32) - ; GFX9-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(s16) = G_FMA [[TRUNC]], [[TRUNC1]], [[TRUNC2]] + ; GFX9-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(s16) = reassoc G_FMA [[TRUNC]], [[TRUNC1]], [[TRUNC2]] ; GFX9-UNSAFE-NEXT: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[FMA]](s16) ; GFX9-UNSAFE-NEXT: $vgpr0 = COPY [[ANYEXT]](s32) ; GFX9-UNSAFE-NEXT: S_SETPC_B64_return $sgpr30_sgpr31, implicit $vgpr0 @@ -426,7 +426,7 @@ body: | ; GFX10-CONTRACT-NEXT: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) ; GFX10-CONTRACT-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $vgpr2 ; GFX10-CONTRACT-NEXT: [[TRUNC2:%[0-9]+]]:_(s16) = G_TRUNC [[COPY2]](s32) - ; GFX10-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(s16) = G_FMA [[TRUNC]], [[TRUNC1]], [[TRUNC2]] + ; GFX10-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(s16) = reassoc G_FMA [[TRUNC]], [[TRUNC1]], [[TRUNC2]] ; GFX10-CONTRACT-NEXT: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[FMA]](s16) ; GFX10-CONTRACT-NEXT: $vgpr0 = COPY [[ANYEXT]](s32) ; GFX10-CONTRACT-NEXT: S_SETPC_B64_return $sgpr30_sgpr31, implicit $vgpr0 @@ -455,7 +455,7 @@ body: | ; GFX10-UNSAFE-NEXT: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) ; GFX10-UNSAFE-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $vgpr2 ; GFX10-UNSAFE-NEXT: [[TRUNC2:%[0-9]+]]:_(s16) = G_TRUNC [[COPY2]](s32) - ; GFX10-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(s16) = G_FMA [[TRUNC]], [[TRUNC1]], [[TRUNC2]] + ; GFX10-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(s16) = reassoc G_FMA [[TRUNC]], [[TRUNC1]], [[TRUNC2]] ; GFX10-UNSAFE-NEXT: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[FMA]](s16) ; GFX10-UNSAFE-NEXT: $vgpr0 = COPY [[ANYEXT]](s32) ; GFX10-UNSAFE-NEXT: S_SETPC_B64_return $sgpr30_sgpr31, implicit $vgpr0 @@ -509,7 +509,7 @@ body: | ; GFX9-CONTRACT-NEXT: [[COPY4:%[0-9]+]]:_(s32) = COPY $vgpr4 ; GFX9-CONTRACT-NEXT: [[COPY5:%[0-9]+]]:_(s32) = COPY $vgpr5 ; GFX9-CONTRACT-NEXT: [[MV2:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY4]](s32), [[COPY5]](s32) - ; GFX9-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(s64) = G_FMA [[MV]], [[MV1]], [[MV2]] + ; GFX9-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(s64) = reassoc G_FMA [[MV]], [[MV1]], [[MV2]] ; GFX9-CONTRACT-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[FMA]](s64) ; GFX9-CONTRACT-NEXT: $vgpr0 = COPY [[UV]](s32) ; GFX9-CONTRACT-NEXT: $vgpr1 = COPY [[UV1]](s32) @@ -546,7 +546,7 @@ body: | ; GFX9-UNSAFE-NEXT: [[COPY4:%[0-9]+]]:_(s32) = COPY $vgpr4 ; GFX9-UNSAFE-NEXT: [[COPY5:%[0-9]+]]:_(s32) = COPY $vgpr5 ; GFX9-UNSAFE-NEXT: [[MV2:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY4]](s32), [[COPY5]](s32) - ; GFX9-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(s64) = G_FMA [[MV]], [[MV1]], [[MV2]] + ; GFX9-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(s64) = reassoc G_FMA [[MV]], [[MV1]], [[MV2]] ; GFX9-UNSAFE-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[FMA]](s64) ; GFX9-UNSAFE-NEXT: $vgpr0 = COPY [[UV]](s32) ; GFX9-UNSAFE-NEXT: $vgpr1 = COPY [[UV1]](s32) @@ -583,7 +583,7 @@ body: | ; GFX10-CONTRACT-NEXT: [[COPY4:%[0-9]+]]:_(s32) = COPY $vgpr4 ; GFX10-CONTRACT-NEXT: [[COPY5:%[0-9]+]]:_(s32) = COPY $vgpr5 ; GFX10-CONTRACT-NEXT: [[MV2:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY4]](s32), [[COPY5]](s32) - ; GFX10-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(s64) = G_FMA [[MV]], [[MV1]], [[MV2]] + ; GFX10-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(s64) = reassoc G_FMA [[MV]], [[MV1]], [[MV2]] ; GFX10-CONTRACT-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[FMA]](s64) ; GFX10-CONTRACT-NEXT: $vgpr0 = COPY [[UV]](s32) ; GFX10-CONTRACT-NEXT: $vgpr1 = COPY [[UV1]](s32) @@ -620,7 +620,7 @@ body: | ; GFX10-UNSAFE-NEXT: [[COPY4:%[0-9]+]]:_(s32) = COPY $vgpr4 ; GFX10-UNSAFE-NEXT: [[COPY5:%[0-9]+]]:_(s32) = COPY $vgpr5 ; GFX10-UNSAFE-NEXT: [[MV2:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY4]](s32), [[COPY5]](s32) - ; GFX10-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(s64) = G_FMA [[MV]], [[MV1]], [[MV2]] + ; GFX10-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(s64) = reassoc G_FMA [[MV]], [[MV1]], [[MV2]] ; GFX10-UNSAFE-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[FMA]](s64) ; GFX10-UNSAFE-NEXT: $vgpr0 = COPY [[UV]](s32) ; GFX10-UNSAFE-NEXT: $vgpr1 = COPY [[UV1]](s32) @@ -679,7 +679,7 @@ body: | ; GFX9-CONTRACT-NEXT: [[COPY4:%[0-9]+]]:_(s32) = COPY $vgpr4 ; GFX9-CONTRACT-NEXT: [[COPY5:%[0-9]+]]:_(s32) = COPY $vgpr5 ; GFX9-CONTRACT-NEXT: [[MV2:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY4]](s32), [[COPY5]](s32) - ; GFX9-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(s64) = G_FMA [[MV]], [[MV1]], [[MV2]] + ; GFX9-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(s64) = reassoc G_FMA [[MV]], [[MV1]], [[MV2]] ; GFX9-CONTRACT-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[FMA]](s64) ; GFX9-CONTRACT-NEXT: $vgpr0 = COPY [[UV]](s32) ; GFX9-CONTRACT-NEXT: $vgpr1 = COPY [[UV1]](s32) @@ -716,7 +716,7 @@ body: | ; GFX9-UNSAFE-NEXT: [[COPY4:%[0-9]+]]:_(s32) = COPY $vgpr4 ; GFX9-UNSAFE-NEXT: [[COPY5:%[0-9]+]]:_(s32) = COPY $vgpr5 ; GFX9-UNSAFE-NEXT: [[MV2:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY4]](s32), [[COPY5]](s32) - ; GFX9-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(s64) = G_FMA [[MV]], [[MV1]], [[MV2]] + ; GFX9-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(s64) = reassoc G_FMA [[MV]], [[MV1]], [[MV2]] ; GFX9-UNSAFE-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[FMA]](s64) ; GFX9-UNSAFE-NEXT: $vgpr0 = COPY [[UV]](s32) ; GFX9-UNSAFE-NEXT: $vgpr1 = COPY [[UV1]](s32) @@ -753,7 +753,7 @@ body: | ; GFX10-CONTRACT-NEXT: [[COPY4:%[0-9]+]]:_(s32) = COPY $vgpr4 ; GFX10-CONTRACT-NEXT: [[COPY5:%[0-9]+]]:_(s32) = COPY $vgpr5 ; GFX10-CONTRACT-NEXT: [[MV2:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY4]](s32), [[COPY5]](s32) - ; GFX10-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(s64) = G_FMA [[MV]], [[MV1]], [[MV2]] + ; GFX10-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(s64) = reassoc G_FMA [[MV]], [[MV1]], [[MV2]] ; GFX10-CONTRACT-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[FMA]](s64) ; GFX10-CONTRACT-NEXT: $vgpr0 = COPY [[UV]](s32) ; GFX10-CONTRACT-NEXT: $vgpr1 = COPY [[UV1]](s32) @@ -790,7 +790,7 @@ body: | ; GFX10-UNSAFE-NEXT: [[COPY4:%[0-9]+]]:_(s32) = COPY $vgpr4 ; GFX10-UNSAFE-NEXT: [[COPY5:%[0-9]+]]:_(s32) = COPY $vgpr5 ; GFX10-UNSAFE-NEXT: [[MV2:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY4]](s32), [[COPY5]](s32) - ; GFX10-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(s64) = G_FMA [[MV]], [[MV1]], [[MV2]] + ; GFX10-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(s64) = reassoc G_FMA [[MV]], [[MV1]], [[MV2]] ; GFX10-UNSAFE-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[FMA]](s64) ; GFX10-UNSAFE-NEXT: $vgpr0 = COPY [[UV]](s32) ; GFX10-UNSAFE-NEXT: $vgpr1 = COPY [[UV1]](s32) @@ -863,7 +863,7 @@ body: | ; GFX9-CONTRACT-NEXT: [[COPY10:%[0-9]+]]:_(s32) = COPY $vgpr10 ; GFX9-CONTRACT-NEXT: [[COPY11:%[0-9]+]]:_(s32) = COPY $vgpr11 ; GFX9-CONTRACT-NEXT: [[BUILD_VECTOR2:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[COPY8]](s32), [[COPY9]](s32), [[COPY10]](s32), [[COPY11]](s32) - ; GFX9-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(<4 x s32>) = G_FMA [[BUILD_VECTOR]], [[BUILD_VECTOR1]], [[BUILD_VECTOR2]] + ; GFX9-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(<4 x s32>) = reassoc G_FMA [[BUILD_VECTOR]], [[BUILD_VECTOR1]], [[BUILD_VECTOR2]] ; GFX9-CONTRACT-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32), [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[FMA]](<4 x s32>) ; GFX9-CONTRACT-NEXT: $vgpr0 = COPY [[UV]](s32) ; GFX9-CONTRACT-NEXT: $vgpr1 = COPY [[UV1]](s32) @@ -916,7 +916,7 @@ body: | ; GFX9-UNSAFE-NEXT: [[COPY10:%[0-9]+]]:_(s32) = COPY $vgpr10 ; GFX9-UNSAFE-NEXT: [[COPY11:%[0-9]+]]:_(s32) = COPY $vgpr11 ; GFX9-UNSAFE-NEXT: [[BUILD_VECTOR2:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[COPY8]](s32), [[COPY9]](s32), [[COPY10]](s32), [[COPY11]](s32) - ; GFX9-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(<4 x s32>) = G_FMA [[BUILD_VECTOR]], [[BUILD_VECTOR1]], [[BUILD_VECTOR2]] + ; GFX9-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(<4 x s32>) = reassoc G_FMA [[BUILD_VECTOR]], [[BUILD_VECTOR1]], [[BUILD_VECTOR2]] ; GFX9-UNSAFE-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32), [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[FMA]](<4 x s32>) ; GFX9-UNSAFE-NEXT: $vgpr0 = COPY [[UV]](s32) ; GFX9-UNSAFE-NEXT: $vgpr1 = COPY [[UV1]](s32) @@ -969,7 +969,7 @@ body: | ; GFX10-CONTRACT-NEXT: [[COPY10:%[0-9]+]]:_(s32) = COPY $vgpr10 ; GFX10-CONTRACT-NEXT: [[COPY11:%[0-9]+]]:_(s32) = COPY $vgpr11 ; GFX10-CONTRACT-NEXT: [[BUILD_VECTOR2:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[COPY8]](s32), [[COPY9]](s32), [[COPY10]](s32), [[COPY11]](s32) - ; GFX10-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(<4 x s32>) = G_FMA [[BUILD_VECTOR]], [[BUILD_VECTOR1]], [[BUILD_VECTOR2]] + ; GFX10-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(<4 x s32>) = reassoc G_FMA [[BUILD_VECTOR]], [[BUILD_VECTOR1]], [[BUILD_VECTOR2]] ; GFX10-CONTRACT-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32), [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[FMA]](<4 x s32>) ; GFX10-CONTRACT-NEXT: $vgpr0 = COPY [[UV]](s32) ; GFX10-CONTRACT-NEXT: $vgpr1 = COPY [[UV1]](s32) @@ -1022,7 +1022,7 @@ body: | ; GFX10-UNSAFE-NEXT: [[COPY10:%[0-9]+]]:_(s32) = COPY $vgpr10 ; GFX10-UNSAFE-NEXT: [[COPY11:%[0-9]+]]:_(s32) = COPY $vgpr11 ; GFX10-UNSAFE-NEXT: [[BUILD_VECTOR2:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[COPY8]](s32), [[COPY9]](s32), [[COPY10]](s32), [[COPY11]](s32) - ; GFX10-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(<4 x s32>) = G_FMA [[BUILD_VECTOR]], [[BUILD_VECTOR1]], [[BUILD_VECTOR2]] + ; GFX10-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(<4 x s32>) = reassoc G_FMA [[BUILD_VECTOR]], [[BUILD_VECTOR1]], [[BUILD_VECTOR2]] ; GFX10-UNSAFE-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32), [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[FMA]](<4 x s32>) ; GFX10-UNSAFE-NEXT: $vgpr0 = COPY [[UV]](s32) ; GFX10-UNSAFE-NEXT: $vgpr1 = COPY [[UV1]](s32) @@ -1098,7 +1098,7 @@ body: | ; GFX9-CONTRACT-NEXT: [[COPY7:%[0-9]+]]:_(s32) = COPY $vgpr7 ; GFX9-CONTRACT-NEXT: [[COPY8:%[0-9]+]]:_(s32) = COPY $vgpr8 ; GFX9-CONTRACT-NEXT: [[BUILD_VECTOR2:%[0-9]+]]:_(<3 x s32>) = G_BUILD_VECTOR [[COPY6]](s32), [[COPY7]](s32), [[COPY8]](s32) - ; GFX9-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(<3 x s32>) = G_FMA [[BUILD_VECTOR]], [[BUILD_VECTOR1]], [[BUILD_VECTOR2]] + ; GFX9-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(<3 x s32>) = reassoc G_FMA [[BUILD_VECTOR]], [[BUILD_VECTOR1]], [[BUILD_VECTOR2]] ; GFX9-CONTRACT-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32), [[UV2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[FMA]](<3 x s32>) ; GFX9-CONTRACT-NEXT: $vgpr0 = COPY [[UV]](s32) ; GFX9-CONTRACT-NEXT: $vgpr1 = COPY [[UV1]](s32) @@ -1143,7 +1143,7 @@ body: | ; GFX9-UNSAFE-NEXT: [[COPY7:%[0-9]+]]:_(s32) = COPY $vgpr7 ; GFX9-UNSAFE-NEXT: [[COPY8:%[0-9]+]]:_(s32) = COPY $vgpr8 ; GFX9-UNSAFE-NEXT: [[BUILD_VECTOR2:%[0-9]+]]:_(<3 x s32>) = G_BUILD_VECTOR [[COPY6]](s32), [[COPY7]](s32), [[COPY8]](s32) - ; GFX9-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(<3 x s32>) = G_FMA [[BUILD_VECTOR]], [[BUILD_VECTOR1]], [[BUILD_VECTOR2]] + ; GFX9-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(<3 x s32>) = reassoc G_FMA [[BUILD_VECTOR]], [[BUILD_VECTOR1]], [[BUILD_VECTOR2]] ; GFX9-UNSAFE-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32), [[UV2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[FMA]](<3 x s32>) ; GFX9-UNSAFE-NEXT: $vgpr0 = COPY [[UV]](s32) ; GFX9-UNSAFE-NEXT: $vgpr1 = COPY [[UV1]](s32) @@ -1188,7 +1188,7 @@ body: | ; GFX10-CONTRACT-NEXT: [[COPY7:%[0-9]+]]:_(s32) = COPY $vgpr7 ; GFX10-CONTRACT-NEXT: [[COPY8:%[0-9]+]]:_(s32) = COPY $vgpr8 ; GFX10-CONTRACT-NEXT: [[BUILD_VECTOR2:%[0-9]+]]:_(<3 x s32>) = G_BUILD_VECTOR [[COPY6]](s32), [[COPY7]](s32), [[COPY8]](s32) - ; GFX10-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(<3 x s32>) = G_FMA [[BUILD_VECTOR]], [[BUILD_VECTOR1]], [[BUILD_VECTOR2]] + ; GFX10-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(<3 x s32>) = reassoc G_FMA [[BUILD_VECTOR]], [[BUILD_VECTOR1]], [[BUILD_VECTOR2]] ; GFX10-CONTRACT-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32), [[UV2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[FMA]](<3 x s32>) ; GFX10-CONTRACT-NEXT: $vgpr0 = COPY [[UV]](s32) ; GFX10-CONTRACT-NEXT: $vgpr1 = COPY [[UV1]](s32) @@ -1233,7 +1233,7 @@ body: | ; GFX10-UNSAFE-NEXT: [[COPY7:%[0-9]+]]:_(s32) = COPY $vgpr7 ; GFX10-UNSAFE-NEXT: [[COPY8:%[0-9]+]]:_(s32) = COPY $vgpr8 ; GFX10-UNSAFE-NEXT: [[BUILD_VECTOR2:%[0-9]+]]:_(<3 x s32>) = G_BUILD_VECTOR [[COPY6]](s32), [[COPY7]](s32), [[COPY8]](s32) - ; GFX10-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(<3 x s32>) = G_FMA [[BUILD_VECTOR]], [[BUILD_VECTOR1]], [[BUILD_VECTOR2]] + ; GFX10-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(<3 x s32>) = reassoc G_FMA [[BUILD_VECTOR]], [[BUILD_VECTOR1]], [[BUILD_VECTOR2]] ; GFX10-UNSAFE-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32), [[UV2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[FMA]](<3 x s32>) ; GFX10-UNSAFE-NEXT: $vgpr0 = COPY [[UV]](s32) ; GFX10-UNSAFE-NEXT: $vgpr1 = COPY [[UV1]](s32) @@ -1297,7 +1297,7 @@ body: | ; GFX9-CONTRACT-NEXT: [[COPY4:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr4 ; GFX9-CONTRACT-NEXT: [[COPY5:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr5 ; GFX9-CONTRACT-NEXT: [[CONCAT_VECTORS2:%[0-9]+]]:_(<4 x s16>) = G_CONCAT_VECTORS [[COPY4]](<2 x s16>), [[COPY5]](<2 x s16>) - ; GFX9-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(<4 x s16>) = G_FMA [[CONCAT_VECTORS]], [[CONCAT_VECTORS1]], [[CONCAT_VECTORS2]] + ; GFX9-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(<4 x s16>) = reassoc G_FMA [[CONCAT_VECTORS]], [[CONCAT_VECTORS1]], [[CONCAT_VECTORS2]] ; GFX9-CONTRACT-NEXT: [[UV:%[0-9]+]]:_(<2 x s16>), [[UV1:%[0-9]+]]:_(<2 x s16>) = G_UNMERGE_VALUES [[FMA]](<4 x s16>) ; GFX9-CONTRACT-NEXT: $vgpr0 = COPY [[UV]](<2 x s16>) ; GFX9-CONTRACT-NEXT: $vgpr1 = COPY [[UV1]](<2 x s16>) @@ -1334,7 +1334,7 @@ body: | ; GFX9-UNSAFE-NEXT: [[COPY4:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr4 ; GFX9-UNSAFE-NEXT: [[COPY5:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr5 ; GFX9-UNSAFE-NEXT: [[CONCAT_VECTORS2:%[0-9]+]]:_(<4 x s16>) = G_CONCAT_VECTORS [[COPY4]](<2 x s16>), [[COPY5]](<2 x s16>) - ; GFX9-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(<4 x s16>) = G_FMA [[CONCAT_VECTORS]], [[CONCAT_VECTORS1]], [[CONCAT_VECTORS2]] + ; GFX9-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(<4 x s16>) = reassoc G_FMA [[CONCAT_VECTORS]], [[CONCAT_VECTORS1]], [[CONCAT_VECTORS2]] ; GFX9-UNSAFE-NEXT: [[UV:%[0-9]+]]:_(<2 x s16>), [[UV1:%[0-9]+]]:_(<2 x s16>) = G_UNMERGE_VALUES [[FMA]](<4 x s16>) ; GFX9-UNSAFE-NEXT: $vgpr0 = COPY [[UV]](<2 x s16>) ; GFX9-UNSAFE-NEXT: $vgpr1 = COPY [[UV1]](<2 x s16>) @@ -1371,7 +1371,7 @@ body: | ; GFX10-CONTRACT-NEXT: [[COPY4:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr4 ; GFX10-CONTRACT-NEXT: [[COPY5:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr5 ; GFX10-CONTRACT-NEXT: [[CONCAT_VECTORS2:%[0-9]+]]:_(<4 x s16>) = G_CONCAT_VECTORS [[COPY4]](<2 x s16>), [[COPY5]](<2 x s16>) - ; GFX10-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(<4 x s16>) = G_FMA [[CONCAT_VECTORS]], [[CONCAT_VECTORS1]], [[CONCAT_VECTORS2]] + ; GFX10-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(<4 x s16>) = reassoc G_FMA [[CONCAT_VECTORS]], [[CONCAT_VECTORS1]], [[CONCAT_VECTORS2]] ; GFX10-CONTRACT-NEXT: [[UV:%[0-9]+]]:_(<2 x s16>), [[UV1:%[0-9]+]]:_(<2 x s16>) = G_UNMERGE_VALUES [[FMA]](<4 x s16>) ; GFX10-CONTRACT-NEXT: $vgpr0 = COPY [[UV]](<2 x s16>) ; GFX10-CONTRACT-NEXT: $vgpr1 = COPY [[UV1]](<2 x s16>) @@ -1408,7 +1408,7 @@ body: | ; GFX10-UNSAFE-NEXT: [[COPY4:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr4 ; GFX10-UNSAFE-NEXT: [[COPY5:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr5 ; GFX10-UNSAFE-NEXT: [[CONCAT_VECTORS2:%[0-9]+]]:_(<4 x s16>) = G_CONCAT_VECTORS [[COPY4]](<2 x s16>), [[COPY5]](<2 x s16>) - ; GFX10-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(<4 x s16>) = G_FMA [[CONCAT_VECTORS]], [[CONCAT_VECTORS1]], [[CONCAT_VECTORS2]] + ; GFX10-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(<4 x s16>) = reassoc G_FMA [[CONCAT_VECTORS]], [[CONCAT_VECTORS1]], [[CONCAT_VECTORS2]] ; GFX10-UNSAFE-NEXT: [[UV:%[0-9]+]]:_(<2 x s16>), [[UV1:%[0-9]+]]:_(<2 x s16>) = G_UNMERGE_VALUES [[FMA]](<4 x s16>) ; GFX10-UNSAFE-NEXT: $vgpr0 = COPY [[UV]](<2 x s16>) ; GFX10-UNSAFE-NEXT: $vgpr1 = COPY [[UV1]](<2 x s16>) @@ -1489,7 +1489,7 @@ body: | ; GFX9-CONTRACT-NEXT: [[BITCAST4:%[0-9]+]]:_(s96) = G_BITCAST [[CONCAT_VECTORS2]](<6 x s16>) ; GFX9-CONTRACT-NEXT: [[TRUNC2:%[0-9]+]]:_(s48) = G_TRUNC [[BITCAST4]](s96) ; GFX9-CONTRACT-NEXT: [[BITCAST5:%[0-9]+]]:_(<3 x s16>) = G_BITCAST [[TRUNC2]](s48) - ; GFX9-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(<3 x s16>) = G_FMA [[BITCAST1]], [[BITCAST3]], [[BITCAST5]] + ; GFX9-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(<3 x s16>) = reassoc G_FMA [[BITCAST1]], [[BITCAST3]], [[BITCAST5]] ; GFX9-CONTRACT-NEXT: [[DEF1:%[0-9]+]]:_(<3 x s16>) = G_IMPLICIT_DEF ; GFX9-CONTRACT-NEXT: [[CONCAT_VECTORS3:%[0-9]+]]:_(<6 x s16>) = G_CONCAT_VECTORS [[FMA]](<3 x s16>), [[DEF1]](<3 x s16>) ; GFX9-CONTRACT-NEXT: [[UV:%[0-9]+]]:_(<2 x s16>), [[UV1:%[0-9]+]]:_(<2 x s16>), [[UV2:%[0-9]+]]:_(<2 x s16>) = G_UNMERGE_VALUES [[CONCAT_VECTORS3]](<6 x s16>) @@ -1550,7 +1550,7 @@ body: | ; GFX9-UNSAFE-NEXT: [[BITCAST4:%[0-9]+]]:_(s96) = G_BITCAST [[CONCAT_VECTORS2]](<6 x s16>) ; GFX9-UNSAFE-NEXT: [[TRUNC2:%[0-9]+]]:_(s48) = G_TRUNC [[BITCAST4]](s96) ; GFX9-UNSAFE-NEXT: [[BITCAST5:%[0-9]+]]:_(<3 x s16>) = G_BITCAST [[TRUNC2]](s48) - ; GFX9-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(<3 x s16>) = G_FMA [[BITCAST1]], [[BITCAST3]], [[BITCAST5]] + ; GFX9-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(<3 x s16>) = reassoc G_FMA [[BITCAST1]], [[BITCAST3]], [[BITCAST5]] ; GFX9-UNSAFE-NEXT: [[DEF1:%[0-9]+]]:_(<3 x s16>) = G_IMPLICIT_DEF ; GFX9-UNSAFE-NEXT: [[CONCAT_VECTORS3:%[0-9]+]]:_(<6 x s16>) = G_CONCAT_VECTORS [[FMA]](<3 x s16>), [[DEF1]](<3 x s16>) ; GFX9-UNSAFE-NEXT: [[UV:%[0-9]+]]:_(<2 x s16>), [[UV1:%[0-9]+]]:_(<2 x s16>), [[UV2:%[0-9]+]]:_(<2 x s16>) = G_UNMERGE_VALUES [[CONCAT_VECTORS3]](<6 x s16>) @@ -1611,7 +1611,7 @@ body: | ; GFX10-CONTRACT-NEXT: [[BITCAST4:%[0-9]+]]:_(s96) = G_BITCAST [[CONCAT_VECTORS2]](<6 x s16>) ; GFX10-CONTRACT-NEXT: [[TRUNC2:%[0-9]+]]:_(s48) = G_TRUNC [[BITCAST4]](s96) ; GFX10-CONTRACT-NEXT: [[BITCAST5:%[0-9]+]]:_(<3 x s16>) = G_BITCAST [[TRUNC2]](s48) - ; GFX10-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(<3 x s16>) = G_FMA [[BITCAST1]], [[BITCAST3]], [[BITCAST5]] + ; GFX10-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(<3 x s16>) = reassoc G_FMA [[BITCAST1]], [[BITCAST3]], [[BITCAST5]] ; GFX10-CONTRACT-NEXT: [[DEF1:%[0-9]+]]:_(<3 x s16>) = G_IMPLICIT_DEF ; GFX10-CONTRACT-NEXT: [[CONCAT_VECTORS3:%[0-9]+]]:_(<6 x s16>) = G_CONCAT_VECTORS [[FMA]](<3 x s16>), [[DEF1]](<3 x s16>) ; GFX10-CONTRACT-NEXT: [[UV:%[0-9]+]]:_(<2 x s16>), [[UV1:%[0-9]+]]:_(<2 x s16>), [[UV2:%[0-9]+]]:_(<2 x s16>) = G_UNMERGE_VALUES [[CONCAT_VECTORS3]](<6 x s16>) @@ -1672,7 +1672,7 @@ body: | ; GFX10-UNSAFE-NEXT: [[BITCAST4:%[0-9]+]]:_(s96) = G_BITCAST [[CONCAT_VECTORS2]](<6 x s16>) ; GFX10-UNSAFE-NEXT: [[TRUNC2:%[0-9]+]]:_(s48) = G_TRUNC [[BITCAST4]](s96) ; GFX10-UNSAFE-NEXT: [[BITCAST5:%[0-9]+]]:_(<3 x s16>) = G_BITCAST [[TRUNC2]](s48) - ; GFX10-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(<3 x s16>) = G_FMA [[BITCAST1]], [[BITCAST3]], [[BITCAST5]] + ; GFX10-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(<3 x s16>) = reassoc G_FMA [[BITCAST1]], [[BITCAST3]], [[BITCAST5]] ; GFX10-UNSAFE-NEXT: [[DEF1:%[0-9]+]]:_(<3 x s16>) = G_IMPLICIT_DEF ; GFX10-UNSAFE-NEXT: [[CONCAT_VECTORS3:%[0-9]+]]:_(<6 x s16>) = G_CONCAT_VECTORS [[FMA]](<3 x s16>), [[DEF1]](<3 x s16>) ; GFX10-UNSAFE-NEXT: [[UV:%[0-9]+]]:_(<2 x s16>), [[UV1:%[0-9]+]]:_(<2 x s16>), [[UV2:%[0-9]+]]:_(<2 x s16>) = G_UNMERGE_VALUES [[CONCAT_VECTORS3]](<6 x s16>) @@ -1805,7 +1805,7 @@ body: | ; GFX9-CONTRACT-NEXT: [[MV10:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY20]](s32), [[COPY21]](s32) ; GFX9-CONTRACT-NEXT: [[MV11:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY22]](s32), [[COPY23]](s32) ; GFX9-CONTRACT-NEXT: [[BUILD_VECTOR2:%[0-9]+]]:_(<4 x s64>) = G_BUILD_VECTOR [[MV8]](s64), [[MV9]](s64), [[MV10]](s64), [[MV11]](s64) - ; GFX9-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(<4 x s64>) = G_FMA [[BUILD_VECTOR]], [[BUILD_VECTOR1]], [[BUILD_VECTOR2]] + ; GFX9-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(<4 x s64>) = reassoc G_FMA [[BUILD_VECTOR]], [[BUILD_VECTOR1]], [[BUILD_VECTOR2]] ; GFX9-CONTRACT-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32), [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32), [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32), [[UV6:%[0-9]+]]:_(s32), [[UV7:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[FMA]](<4 x s64>) ; GFX9-CONTRACT-NEXT: $vgpr0 = COPY [[UV]](s32) ; GFX9-CONTRACT-NEXT: $vgpr1 = COPY [[UV1]](s32) @@ -1914,7 +1914,7 @@ body: | ; GFX9-UNSAFE-NEXT: [[MV10:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY20]](s32), [[COPY21]](s32) ; GFX9-UNSAFE-NEXT: [[MV11:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY22]](s32), [[COPY23]](s32) ; GFX9-UNSAFE-NEXT: [[BUILD_VECTOR2:%[0-9]+]]:_(<4 x s64>) = G_BUILD_VECTOR [[MV8]](s64), [[MV9]](s64), [[MV10]](s64), [[MV11]](s64) - ; GFX9-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(<4 x s64>) = G_FMA [[BUILD_VECTOR]], [[BUILD_VECTOR1]], [[BUILD_VECTOR2]] + ; GFX9-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(<4 x s64>) = reassoc G_FMA [[BUILD_VECTOR]], [[BUILD_VECTOR1]], [[BUILD_VECTOR2]] ; GFX9-UNSAFE-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32), [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32), [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32), [[UV6:%[0-9]+]]:_(s32), [[UV7:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[FMA]](<4 x s64>) ; GFX9-UNSAFE-NEXT: $vgpr0 = COPY [[UV]](s32) ; GFX9-UNSAFE-NEXT: $vgpr1 = COPY [[UV1]](s32) @@ -2023,7 +2023,7 @@ body: | ; GFX10-CONTRACT-NEXT: [[MV10:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY20]](s32), [[COPY21]](s32) ; GFX10-CONTRACT-NEXT: [[MV11:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY22]](s32), [[COPY23]](s32) ; GFX10-CONTRACT-NEXT: [[BUILD_VECTOR2:%[0-9]+]]:_(<4 x s64>) = G_BUILD_VECTOR [[MV8]](s64), [[MV9]](s64), [[MV10]](s64), [[MV11]](s64) - ; GFX10-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(<4 x s64>) = G_FMA [[BUILD_VECTOR]], [[BUILD_VECTOR1]], [[BUILD_VECTOR2]] + ; GFX10-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(<4 x s64>) = reassoc G_FMA [[BUILD_VECTOR]], [[BUILD_VECTOR1]], [[BUILD_VECTOR2]] ; GFX10-CONTRACT-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32), [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32), [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32), [[UV6:%[0-9]+]]:_(s32), [[UV7:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[FMA]](<4 x s64>) ; GFX10-CONTRACT-NEXT: $vgpr0 = COPY [[UV]](s32) ; GFX10-CONTRACT-NEXT: $vgpr1 = COPY [[UV1]](s32) @@ -2132,7 +2132,7 @@ body: | ; GFX10-UNSAFE-NEXT: [[MV10:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY20]](s32), [[COPY21]](s32) ; GFX10-UNSAFE-NEXT: [[MV11:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY22]](s32), [[COPY23]](s32) ; GFX10-UNSAFE-NEXT: [[BUILD_VECTOR2:%[0-9]+]]:_(<4 x s64>) = G_BUILD_VECTOR [[MV8]](s64), [[MV9]](s64), [[MV10]](s64), [[MV11]](s64) - ; GFX10-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(<4 x s64>) = G_FMA [[BUILD_VECTOR]], [[BUILD_VECTOR1]], [[BUILD_VECTOR2]] + ; GFX10-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(<4 x s64>) = reassoc G_FMA [[BUILD_VECTOR]], [[BUILD_VECTOR1]], [[BUILD_VECTOR2]] ; GFX10-UNSAFE-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32), [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32), [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32), [[UV6:%[0-9]+]]:_(s32), [[UV7:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[FMA]](<4 x s64>) ; GFX10-UNSAFE-NEXT: $vgpr0 = COPY [[UV]](s32) ; GFX10-UNSAFE-NEXT: $vgpr1 = COPY [[UV1]](s32) @@ -2279,7 +2279,7 @@ body: | ; GFX9-CONTRACT-NEXT: [[MV7:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY14]](s32), [[COPY15]](s32) ; GFX9-CONTRACT-NEXT: [[MV8:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY16]](s32), [[COPY17]](s32) ; GFX9-CONTRACT-NEXT: [[BUILD_VECTOR2:%[0-9]+]]:_(<3 x s64>) = G_BUILD_VECTOR [[MV6]](s64), [[MV7]](s64), [[MV8]](s64) - ; GFX9-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(<3 x s64>) = G_FMA [[BUILD_VECTOR]], [[BUILD_VECTOR1]], [[BUILD_VECTOR2]] + ; GFX9-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(<3 x s64>) = reassoc G_FMA [[BUILD_VECTOR]], [[BUILD_VECTOR1]], [[BUILD_VECTOR2]] ; GFX9-CONTRACT-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32), [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32), [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[FMA]](<3 x s64>) ; GFX9-CONTRACT-NEXT: $vgpr0 = COPY [[UV]](s32) ; GFX9-CONTRACT-NEXT: $vgpr1 = COPY [[UV1]](s32) @@ -2366,7 +2366,7 @@ body: | ; GFX9-UNSAFE-NEXT: [[MV7:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY14]](s32), [[COPY15]](s32) ; GFX9-UNSAFE-NEXT: [[MV8:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY16]](s32), [[COPY17]](s32) ; GFX9-UNSAFE-NEXT: [[BUILD_VECTOR2:%[0-9]+]]:_(<3 x s64>) = G_BUILD_VECTOR [[MV6]](s64), [[MV7]](s64), [[MV8]](s64) - ; GFX9-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(<3 x s64>) = G_FMA [[BUILD_VECTOR]], [[BUILD_VECTOR1]], [[BUILD_VECTOR2]] + ; GFX9-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(<3 x s64>) = reassoc G_FMA [[BUILD_VECTOR]], [[BUILD_VECTOR1]], [[BUILD_VECTOR2]] ; GFX9-UNSAFE-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32), [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32), [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[FMA]](<3 x s64>) ; GFX9-UNSAFE-NEXT: $vgpr0 = COPY [[UV]](s32) ; GFX9-UNSAFE-NEXT: $vgpr1 = COPY [[UV1]](s32) @@ -2453,7 +2453,7 @@ body: | ; GFX10-CONTRACT-NEXT: [[MV7:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY14]](s32), [[COPY15]](s32) ; GFX10-CONTRACT-NEXT: [[MV8:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY16]](s32), [[COPY17]](s32) ; GFX10-CONTRACT-NEXT: [[BUILD_VECTOR2:%[0-9]+]]:_(<3 x s64>) = G_BUILD_VECTOR [[MV6]](s64), [[MV7]](s64), [[MV8]](s64) - ; GFX10-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(<3 x s64>) = G_FMA [[BUILD_VECTOR]], [[BUILD_VECTOR1]], [[BUILD_VECTOR2]] + ; GFX10-CONTRACT-NEXT: [[FMA:%[0-9]+]]:_(<3 x s64>) = reassoc G_FMA [[BUILD_VECTOR]], [[BUILD_VECTOR1]], [[BUILD_VECTOR2]] ; GFX10-CONTRACT-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32), [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32), [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[FMA]](<3 x s64>) ; GFX10-CONTRACT-NEXT: $vgpr0 = COPY [[UV]](s32) ; GFX10-CONTRACT-NEXT: $vgpr1 = COPY [[UV1]](s32) @@ -2540,7 +2540,7 @@ body: | ; GFX10-UNSAFE-NEXT: [[MV7:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY14]](s32), [[COPY15]](s32) ; GFX10-UNSAFE-NEXT: [[MV8:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY16]](s32), [[COPY17]](s32) ; GFX10-UNSAFE-NEXT: [[BUILD_VECTOR2:%[0-9]+]]:_(<3 x s64>) = G_BUILD_VECTOR [[MV6]](s64), [[MV7]](s64), [[MV8]](s64) - ; GFX10-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(<3 x s64>) = G_FMA [[BUILD_VECTOR]], [[BUILD_VECTOR1]], [[BUILD_VECTOR2]] + ; GFX10-UNSAFE-NEXT: [[FMA:%[0-9]+]]:_(<3 x s64>) = reassoc G_FMA [[BUILD_VECTOR]], [[BUILD_VECTOR1]], [[BUILD_VECTOR2]] ; GFX10-UNSAFE-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32), [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32), [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[FMA]](<3 x s64>) ; GFX10-UNSAFE-NEXT: $vgpr0 = COPY [[UV]](s32) ; GFX10-UNSAFE-NEXT: $vgpr1 = COPY [[UV1]](s32) diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/combine-fma-unmerge-values.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/combine-fma-unmerge-values.mir index 291f478e08fae..dccf970a364a1 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/combine-fma-unmerge-values.mir +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/combine-fma-unmerge-values.mir @@ -79,9 +79,9 @@ body: | ; GFX10-NEXT: %ptr:_(p1) = COPY $vgpr0_vgpr1 ; GFX10-NEXT: %vec:_(<2 x s32>) = G_LOAD %ptr(p1) :: (load (<2 x s32>), addrspace 1) ; GFX10-NEXT: %el0:_(s32), %el1:_(s32) = G_UNMERGE_VALUES %vec(<2 x s32>) - ; GFX10-NEXT: [[FPEXT:%[0-9]+]]:_(s32) = G_FPEXT [[TRUNC]](s16) - ; GFX10-NEXT: [[FPEXT1:%[0-9]+]]:_(s32) = G_FPEXT [[TRUNC1]](s16) - ; GFX10-NEXT: [[FMA:%[0-9]+]]:_(s32) = G_FMA [[FPEXT]], [[FPEXT1]], %el1 + ; GFX10-NEXT: [[FPEXT:%[0-9]+]]:_(s32) = nnan ninf nsz arcp contract afn reassoc G_FPEXT [[TRUNC]](s16) + ; GFX10-NEXT: [[FPEXT1:%[0-9]+]]:_(s32) = nnan ninf nsz arcp contract afn reassoc G_FPEXT [[TRUNC1]](s16) + ; GFX10-NEXT: [[FMA:%[0-9]+]]:_(s32) = nnan ninf nsz arcp contract afn reassoc G_FMA [[FPEXT]], [[FPEXT1]], %el1 ; GFX10-NEXT: $vgpr0 = COPY [[FMA]](s32) %0:_(s32) = COPY $sgpr0 %1:_(s16) = G_TRUNC %0(s32) @@ -116,9 +116,9 @@ body: | ; GFX10-NEXT: %ptr:_(p1) = COPY $vgpr0_vgpr1 ; GFX10-NEXT: %vec:_(<2 x s32>) = G_LOAD %ptr(p1) :: (load (<2 x s32>), addrspace 1) ; GFX10-NEXT: %el0:_(s32), %el1:_(s32) = G_UNMERGE_VALUES %vec(<2 x s32>) - ; GFX10-NEXT: [[FPEXT:%[0-9]+]]:_(s32) = G_FPEXT [[TRUNC]](s16) - ; GFX10-NEXT: [[FPEXT1:%[0-9]+]]:_(s32) = G_FPEXT [[TRUNC1]](s16) - ; GFX10-NEXT: [[FMA:%[0-9]+]]:_(s32) = G_FMA [[FPEXT]], [[FPEXT1]], %el1 + ; GFX10-NEXT: [[FPEXT:%[0-9]+]]:_(s32) = nnan ninf nsz arcp contract afn reassoc G_FPEXT [[TRUNC]](s16) + ; GFX10-NEXT: [[FPEXT1:%[0-9]+]]:_(s32) = nnan ninf nsz arcp contract afn reassoc G_FPEXT [[TRUNC1]](s16) + ; GFX10-NEXT: [[FMA:%[0-9]+]]:_(s32) = nnan ninf nsz arcp contract afn reassoc G_FMA [[FPEXT]], [[FPEXT1]], %el1 ; GFX10-NEXT: $vgpr0 = COPY [[FMA]](s32) %0:_(s32) = COPY $sgpr0 %1:_(s16) = G_TRUNC %0(s32) @@ -149,8 +149,8 @@ body: | ; GFX10-NEXT: %ptr:_(p1) = COPY $vgpr4_vgpr5 ; GFX10-NEXT: %vec:_(<2 x s32>) = G_LOAD %ptr(p1) :: (load (<2 x s32>), addrspace 1) ; GFX10-NEXT: %el0:_(s32), %el1:_(s32) = G_UNMERGE_VALUES %vec(<2 x s32>) - ; GFX10-NEXT: [[FMA:%[0-9]+]]:_(s32) = G_FMA [[COPY2]], [[COPY3]], %el1 - ; GFX10-NEXT: [[FMA1:%[0-9]+]]:_(s32) = G_FMA [[COPY]], [[COPY1]], [[FMA]] + ; GFX10-NEXT: [[FMA:%[0-9]+]]:_(s32) = nnan ninf nsz arcp contract afn reassoc G_FMA [[COPY2]], [[COPY3]], %el1 + ; GFX10-NEXT: [[FMA1:%[0-9]+]]:_(s32) = nnan ninf nsz arcp contract afn reassoc G_FMA [[COPY]], [[COPY1]], [[FMA]] ; GFX10-NEXT: $vgpr0 = COPY [[FMA1]](s32) %0:_(s32) = COPY $vgpr0 %1:_(s32) = COPY $vgpr1 @@ -181,8 +181,8 @@ body: | ; GFX10-NEXT: %ptr:_(p1) = COPY $vgpr4_vgpr5 ; GFX10-NEXT: %vec:_(<2 x s32>) = G_LOAD %ptr(p1) :: (load (<2 x s32>), addrspace 1) ; GFX10-NEXT: %el0:_(s32), %el1:_(s32) = G_UNMERGE_VALUES %vec(<2 x s32>) - ; GFX10-NEXT: [[FMA:%[0-9]+]]:_(s32) = G_FMA [[COPY2]], [[COPY3]], %el1 - ; GFX10-NEXT: [[FMA1:%[0-9]+]]:_(s32) = G_FMA [[COPY]], [[COPY1]], [[FMA]] + ; GFX10-NEXT: [[FMA:%[0-9]+]]:_(s32) = nnan ninf nsz arcp contract afn reassoc G_FMA [[COPY2]], [[COPY3]], %el1 + ; GFX10-NEXT: [[FMA1:%[0-9]+]]:_(s32) = nnan ninf nsz arcp contract afn reassoc G_FMA [[COPY]], [[COPY1]], [[FMA]] ; GFX10-NEXT: $vgpr0 = COPY [[FMA1]](s32) %0:_(s32) = COPY $vgpr0 %1:_(s32) = COPY $vgpr1 diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/combine-fold-binop-into-select.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/combine-fold-binop-into-select.mir index 9f3ad8b444446..8a16ab53804a3 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/combine-fold-binop-into-select.mir +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/combine-fold-binop-into-select.mir @@ -1034,8 +1034,8 @@ body: | ; CHECK-NEXT: %reg:_(s32) = COPY $vgpr0 ; CHECK-NEXT: %zero:_(s32) = G_CONSTANT i32 0 ; CHECK-NEXT: %cond:_(s1) = G_ICMP intpred(eq), %reg(s32), %zero - ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_FCONSTANT float 1.800000e+01 - ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_FCONSTANT float 2.000000e+01 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = nnan G_FCONSTANT float 1.800000e+01 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = nnan G_FCONSTANT float 2.000000e+01 ; CHECK-NEXT: %fadd:_(s32) = nnan G_SELECT %cond(s1), [[C]], [[C1]] ; CHECK-NEXT: S_ENDPGM 0, implicit %fadd(s32) %reg:_(s32) = COPY $vgpr0 @@ -1061,8 +1061,8 @@ body: | ; CHECK-NEXT: %reg:_(s32) = COPY $vgpr0 ; CHECK-NEXT: %zero:_(s32) = G_CONSTANT i32 0 ; CHECK-NEXT: %cond:_(s1) = G_ICMP intpred(eq), %reg(s32), %zero - ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_FCONSTANT float 1.800000e+01 - ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_FCONSTANT float 2.000000e+01 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = nnan G_FCONSTANT float 1.800000e+01 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = nnan G_FCONSTANT float 2.000000e+01 ; CHECK-NEXT: %fadd:_(s32) = nnan G_SELECT %cond(s1), [[C]], [[C1]] ; CHECK-NEXT: S_ENDPGM 0, implicit %fadd(s32) %reg:_(s32) = COPY $vgpr0 @@ -1088,8 +1088,8 @@ body: | ; CHECK-NEXT: %reg:_(s32) = COPY $vgpr0 ; CHECK-NEXT: %zero:_(s32) = G_CONSTANT i32 0 ; CHECK-NEXT: %cond:_(s1) = G_ICMP intpred(eq), %reg(s32), %zero - ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_FCONSTANT float -1.400000e+01 - ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_FCONSTANT float -1.200000e+01 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = nnan G_FCONSTANT float -1.400000e+01 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = nnan G_FCONSTANT float -1.200000e+01 ; CHECK-NEXT: %fsub:_(s32) = nnan G_SELECT %cond(s1), [[C]], [[C1]] ; CHECK-NEXT: S_ENDPGM 0, implicit %fsub(s32) %reg:_(s32) = COPY $vgpr0 @@ -1115,8 +1115,8 @@ body: | ; CHECK-NEXT: %reg:_(s32) = COPY $vgpr0 ; CHECK-NEXT: %zero:_(s32) = G_CONSTANT i32 0 ; CHECK-NEXT: %cond:_(s1) = G_ICMP intpred(eq), %reg(s32), %zero - ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_FCONSTANT float 3.200000e+01 - ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_FCONSTANT float 6.400000e+01 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = nnan G_FCONSTANT float 3.200000e+01 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = nnan G_FCONSTANT float 6.400000e+01 ; CHECK-NEXT: %fmul:_(s32) = nnan G_SELECT %cond(s1), [[C]], [[C1]] ; CHECK-NEXT: S_ENDPGM 0, implicit %fmul(s32) %reg:_(s32) = COPY $vgpr0 @@ -1142,8 +1142,8 @@ body: | ; CHECK-NEXT: %reg:_(s32) = COPY $vgpr0 ; CHECK-NEXT: %zero:_(s32) = G_CONSTANT i32 0 ; CHECK-NEXT: %cond:_(s1) = G_ICMP intpred(eq), %reg(s32), %zero - ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_FCONSTANT float 1.250000e-01 - ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_FCONSTANT float 2.500000e-01 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = nnan G_FCONSTANT float 1.250000e-01 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = nnan G_FCONSTANT float 2.500000e-01 ; CHECK-NEXT: %fdiv:_(s32) = nnan G_SELECT %cond(s1), [[C]], [[C1]] ; CHECK-NEXT: S_ENDPGM 0, implicit %fdiv(s32) %reg:_(s32) = COPY $vgpr0 diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/combine-fsub-fneg.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/combine-fsub-fneg.mir index 2bce205735299..bb7014ae4546b 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/combine-fsub-fneg.mir +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/combine-fsub-fneg.mir @@ -13,8 +13,8 @@ body: | ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; CHECK-NEXT: %input:_(s16) = G_TRUNC [[COPY]](s32) - ; CHECK-NEXT: [[FNEG:%[0-9]+]]:_(s16) = G_FNEG %input - ; CHECK-NEXT: [[FCANONICALIZE:%[0-9]+]]:_(s16) = G_FCANONICALIZE [[FNEG]] + ; CHECK-NEXT: [[FNEG:%[0-9]+]]:_(s16) = nsz G_FNEG %input + ; CHECK-NEXT: [[FCANONICALIZE:%[0-9]+]]:_(s16) = nsz G_FCANONICALIZE [[FNEG]] ; CHECK-NEXT: %res:_(s32) = G_ANYEXT [[FCANONICALIZE]](s16) ; CHECK-NEXT: $vgpr0 = COPY %res(s32) %0:_(s32) = COPY $vgpr0 @@ -84,8 +84,8 @@ body: | ; CHECK: liveins: $vgpr0 ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: %input:_(s32) = COPY $vgpr0 - ; CHECK-NEXT: [[FNEG:%[0-9]+]]:_(s32) = G_FNEG %input - ; CHECK-NEXT: [[FCANONICALIZE:%[0-9]+]]:_(s32) = G_FCANONICALIZE [[FNEG]] + ; CHECK-NEXT: [[FNEG:%[0-9]+]]:_(s32) = nsz G_FNEG %input + ; CHECK-NEXT: [[FCANONICALIZE:%[0-9]+]]:_(s32) = nsz G_FCANONICALIZE [[FNEG]] ; CHECK-NEXT: $vgpr0 = COPY [[FCANONICALIZE]](s32) %input:_(s32) = COPY $vgpr0 %cst:_(s32) = G_FCONSTANT float 0.0 @@ -144,8 +144,8 @@ body: | ; CHECK: liveins: $vgpr0_vgpr1 ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: %input:_(s64) = COPY $vgpr0_vgpr1 - ; CHECK-NEXT: [[FNEG:%[0-9]+]]:_(s64) = G_FNEG %input - ; CHECK-NEXT: [[FCANONICALIZE:%[0-9]+]]:_(s64) = G_FCANONICALIZE [[FNEG]] + ; CHECK-NEXT: [[FNEG:%[0-9]+]]:_(s64) = nsz G_FNEG %input + ; CHECK-NEXT: [[FCANONICALIZE:%[0-9]+]]:_(s64) = nsz G_FCANONICALIZE [[FNEG]] ; CHECK-NEXT: $vgpr0_vgpr1 = COPY [[FCANONICALIZE]](s64) %input:_(s64) = COPY $vgpr0_vgpr1 %cst:_(s64) = G_FCONSTANT double 0.0 @@ -204,8 +204,8 @@ body: | ; CHECK: liveins: $vgpr0_vgpr1 ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: %input:_(<4 x s16>) = COPY $vgpr0_vgpr1 - ; CHECK-NEXT: [[FNEG:%[0-9]+]]:_(<4 x s16>) = G_FNEG %input - ; CHECK-NEXT: [[FCANONICALIZE:%[0-9]+]]:_(<4 x s16>) = G_FCANONICALIZE [[FNEG]] + ; CHECK-NEXT: [[FNEG:%[0-9]+]]:_(<4 x s16>) = nsz G_FNEG %input + ; CHECK-NEXT: [[FCANONICALIZE:%[0-9]+]]:_(<4 x s16>) = nsz G_FCANONICALIZE [[FNEG]] ; CHECK-NEXT: $vgpr0_vgpr1 = COPY [[FCANONICALIZE]](<4 x s16>) %input:_(<4 x s16>) = COPY $vgpr0_vgpr1 %cst:_(s16) = G_FCONSTANT half 0.0 @@ -268,8 +268,8 @@ body: | ; CHECK: liveins: $vgpr0_vgpr1_vgpr2_vgpr3 ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: %input:_(<4 x s32>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 - ; CHECK-NEXT: [[FNEG:%[0-9]+]]:_(<4 x s32>) = G_FNEG %input - ; CHECK-NEXT: [[FCANONICALIZE:%[0-9]+]]:_(<4 x s32>) = G_FCANONICALIZE [[FNEG]] + ; CHECK-NEXT: [[FNEG:%[0-9]+]]:_(<4 x s32>) = nsz G_FNEG %input + ; CHECK-NEXT: [[FCANONICALIZE:%[0-9]+]]:_(<4 x s32>) = nsz G_FCANONICALIZE [[FNEG]] ; CHECK-NEXT: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[FCANONICALIZE]](<4 x s32>) %input:_(<4 x s32>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 %cst:_(s32) = G_FCONSTANT float 0.0 @@ -332,8 +332,8 @@ body: | ; CHECK: liveins: $vgpr0_vgpr1_vgpr2_vgpr3 ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: %input:_(<4 x s32>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 - ; CHECK-NEXT: [[FNEG:%[0-9]+]]:_(<4 x s32>) = G_FNEG %input - ; CHECK-NEXT: [[FCANONICALIZE:%[0-9]+]]:_(<4 x s32>) = G_FCANONICALIZE [[FNEG]] + ; CHECK-NEXT: [[FNEG:%[0-9]+]]:_(<4 x s32>) = nsz G_FNEG %input + ; CHECK-NEXT: [[FCANONICALIZE:%[0-9]+]]:_(<4 x s32>) = nsz G_FCANONICALIZE [[FNEG]] ; CHECK-NEXT: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[FCANONICALIZE]](<4 x s32>) %input:_(<4 x s32>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 %cst:_(s32) = G_FCONSTANT float 0.0 @@ -354,8 +354,8 @@ body: | ; CHECK: liveins: $vgpr0_vgpr1_vgpr2_vgpr3 ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: %input:_(<2 x s64>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 - ; CHECK-NEXT: [[FNEG:%[0-9]+]]:_(<2 x s64>) = G_FNEG %input - ; CHECK-NEXT: [[FCANONICALIZE:%[0-9]+]]:_(<2 x s64>) = G_FCANONICALIZE [[FNEG]] + ; CHECK-NEXT: [[FNEG:%[0-9]+]]:_(<2 x s64>) = nsz G_FNEG %input + ; CHECK-NEXT: [[FCANONICALIZE:%[0-9]+]]:_(<2 x s64>) = nsz G_FCANONICALIZE [[FNEG]] ; CHECK-NEXT: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[FCANONICALIZE]](<2 x s64>) %input:_(<2 x s64>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 %cst:_(s64) = G_FCONSTANT double 0.0 diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-imms.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-imms.td index b3e7ba28b0fa3..ec08e8b92326f 100644 --- a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-imms.td +++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-imms.td @@ -48,7 +48,7 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0, // CHECK-NEXT: GIR_Done, // CHECK-NEXT: // Label 0: @28 -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 1*/ 67, // Rule ID 1 // +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 1*/ 59, // Rule ID 1 // // CHECK-NEXT: GIM_CheckSimplePredicate, GICXXPred_Simple_IsRule1Enabled, // CHECK-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_ZEXT, // CHECK-NEXT: // MIs[0] a @@ -56,17 +56,15 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: // MIs[0] Operand 1 // CHECK-NEXT: GIM_CheckConstantInt, /*MI*/0, /*Op*/1, 0, // CHECK-NEXT: GIR_MakeTempReg, /*TempRegID*/0, /*TypeID*/GILLT_s32, -// CHECK-NEXT: GIR_BuildMI, /*InsnID*/1, /*Opcode*/TargetOpcode::G_CONSTANT, -// CHECK-NEXT: GIR_AddTempRegister, /*InsnID*/1, /*TempRegID*/0, /*TempRegFlags*/0, -// CHECK-NEXT: GIR_AddCImm, /*InsnID*/1, /*Type*/GILLT_s32, /*Imm*/0, +// CHECK-NEXT: GIR_BuildConstant, /*TempRegID*/0, /*Val*/0, // CHECK-NEXT: // Combiner Rule #1: InstTest1 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/TargetOpcode::COPY, // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // a // CHECK-NEXT: GIR_AddTempRegister, /*InsnID*/0, /*TempRegID*/0, /*TempRegFlags*/0, // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0, // CHECK-NEXT: GIR_Done, -// CHECK-NEXT: // Label 1: @67 -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 2*/ 96, // Rule ID 2 // +// CHECK-NEXT: // Label 1: @59 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 2*/ 88, // Rule ID 2 // // CHECK-NEXT: GIM_CheckSimplePredicate, GICXXPred_Simple_IsRule2Enabled, // CHECK-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_CONSTANT, // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/1, /*Type*/GILLT_s32, @@ -79,7 +77,7 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: GIR_AddCImm, /*InsnID*/0, /*Type*/GILLT_s32, /*Imm*/42, // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0, // CHECK-NEXT: GIR_Done, -// CHECK-NEXT: // Label 2: @96 +// CHECK-NEXT: // Label 2: @88 // CHECK-NEXT: GIM_Reject, // CHECK-NEXT: }; // CHECK-NEXT: return MatchTable0; diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-patfrag-root.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-patfrag-root.td index 21a31a9fc5bf5..c314b2a35d77a 100644 --- a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-patfrag-root.td +++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-patfrag-root.td @@ -28,7 +28,7 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK: const int64_t *GenMyCombiner::getMatchTable() const { // CHECK-NEXT: constexpr static int64_t MatchTable0[] = { -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 0*/ 44, // Rule ID 0 // +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 0*/ 36, // Rule ID 0 // // CHECK-NEXT: GIM_CheckSimplePredicate, GICXXPred_Simple_IsRule0Enabled, // CHECK-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_ZEXT, // CHECK-NEXT: // MIs[0] root @@ -40,17 +40,15 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: // No operand predicates // CHECK-NEXT: GIM_CheckIsSafeToFold, /*InsnID*/1, // CHECK-NEXT: GIR_MakeTempReg, /*TempRegID*/0, /*TypeID*/GILLT_s32, -// CHECK-NEXT: GIR_BuildMI, /*InsnID*/1, /*Opcode*/TargetOpcode::G_CONSTANT, -// CHECK-NEXT: GIR_AddTempRegister, /*InsnID*/1, /*TempRegID*/0, /*TempRegFlags*/0, -// CHECK-NEXT: GIR_AddCImm, /*InsnID*/1, /*Type*/GILLT_s32, /*Imm*/0, +// CHECK-NEXT: GIR_BuildConstant, /*TempRegID*/0, /*Val*/0, // CHECK-NEXT: // Combiner Rule #0: Test0 @ [__Test0_match_0[0]] // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/TargetOpcode::COPY, // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // root // CHECK-NEXT: GIR_AddTempRegister, /*InsnID*/0, /*TempRegID*/0, /*TempRegFlags*/0, // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0, // CHECK-NEXT: GIR_Done, -// CHECK-NEXT: // Label 0: @44 -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 1*/ 79, // Rule ID 1 // +// CHECK-NEXT: // Label 0: @36 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 1*/ 63, // Rule ID 1 // // CHECK-NEXT: GIM_CheckSimplePredicate, GICXXPred_Simple_IsRule0Enabled, // CHECK-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_TRUNC, // CHECK-NEXT: // MIs[0] root @@ -58,17 +56,15 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: // MIs[0] __Test0_match_0.z // CHECK-NEXT: // No operand predicates // CHECK-NEXT: GIR_MakeTempReg, /*TempRegID*/0, /*TypeID*/GILLT_s32, -// CHECK-NEXT: GIR_BuildMI, /*InsnID*/1, /*Opcode*/TargetOpcode::G_CONSTANT, -// CHECK-NEXT: GIR_AddTempRegister, /*InsnID*/1, /*TempRegID*/0, /*TempRegFlags*/0, -// CHECK-NEXT: GIR_AddCImm, /*InsnID*/1, /*Type*/GILLT_s32, /*Imm*/0, +// CHECK-NEXT: GIR_BuildConstant, /*TempRegID*/0, /*Val*/0, // CHECK-NEXT: // Combiner Rule #0: Test0 @ [__Test0_match_0[1]] // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/TargetOpcode::COPY, // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // root // CHECK-NEXT: GIR_AddTempRegister, /*InsnID*/0, /*TempRegID*/0, /*TempRegFlags*/0, // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0, // CHECK-NEXT: GIR_Done, -// CHECK-NEXT: // Label 1: @79 -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 2*/ 114, // Rule ID 2 // +// CHECK-NEXT: // Label 1: @63 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 2*/ 90, // Rule ID 2 // // CHECK-NEXT: GIM_CheckSimplePredicate, GICXXPred_Simple_IsRule0Enabled, // CHECK-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_FPEXT, // CHECK-NEXT: // MIs[0] root @@ -76,16 +72,14 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: // MIs[0] __Test0_match_0.z // CHECK-NEXT: // No operand predicates // CHECK-NEXT: GIR_MakeTempReg, /*TempRegID*/0, /*TypeID*/GILLT_s32, -// CHECK-NEXT: GIR_BuildMI, /*InsnID*/1, /*Opcode*/TargetOpcode::G_CONSTANT, -// CHECK-NEXT: GIR_AddTempRegister, /*InsnID*/1, /*TempRegID*/0, /*TempRegFlags*/0, -// CHECK-NEXT: GIR_AddCImm, /*InsnID*/1, /*Type*/GILLT_s32, /*Imm*/0, +// CHECK-NEXT: GIR_BuildConstant, /*TempRegID*/0, /*Val*/0, // CHECK-NEXT: // Combiner Rule #0: Test0 @ [__Test0_match_0[2]] // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/TargetOpcode::COPY, // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // root // CHECK-NEXT: GIR_AddTempRegister, /*InsnID*/0, /*TempRegID*/0, /*TempRegFlags*/0, // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0, // CHECK-NEXT: GIR_Done, -// CHECK-NEXT: // Label 2: @114 +// CHECK-NEXT: // Label 2: @90 // CHECK-NEXT: GIM_Reject, // CHECK-NEXT: }; // CHECK-NEXT: return MatchTable0; diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-permutations.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-permutations.td index e6825ba6607ea..1bede1a158768 100644 --- a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-permutations.td +++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-permutations.td @@ -159,9 +159,9 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK: const int64_t *GenMyCombiner::getMatchTable() const { // CHECK-NEXT: constexpr static int64_t MatchTable0[] = { -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 0*/ 746, +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 0*/ 682, // CHECK-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_AND, -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 1*/ 111, // Rule ID 0 // +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 1*/ 103, // Rule ID 0 // // CHECK-NEXT: GIM_CheckSimplePredicate, GICXXPred_Simple_IsRule0Enabled, // CHECK-NEXT: // MIs[0] dst // CHECK-NEXT: // No operand predicates @@ -203,9 +203,7 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: GIM_CheckIsSafeToFold, /*InsnID*/6, // CHECK-NEXT: GIM_CheckIsSafeToFold, /*InsnID*/7, // CHECK-NEXT: GIR_MakeTempReg, /*TempRegID*/0, /*TypeID*/GILLT_s32, -// CHECK-NEXT: GIR_BuildMI, /*InsnID*/1, /*Opcode*/TargetOpcode::G_CONSTANT, -// CHECK-NEXT: GIR_AddTempRegister, /*InsnID*/1, /*TempRegID*/0, /*TempRegFlags*/0, -// CHECK-NEXT: GIR_AddCImm, /*InsnID*/1, /*Type*/GILLT_s32, /*Imm*/0, +// CHECK-NEXT: GIR_BuildConstant, /*TempRegID*/0, /*Val*/0, // CHECK-NEXT: // Combiner Rule #0: Test0 @ [a[0], b[0], c[0]] // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/TargetOpcode::COPY, // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst @@ -213,8 +211,8 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0, // CHECK-NEXT: GIR_CustomAction, GICXXCustomAction_CombineApplyGICombiner0, // CHECK-NEXT: GIR_Done, -// CHECK-NEXT: // Label 1: @111 -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 2*/ 208, // Rule ID 1 // +// CHECK-NEXT: // Label 1: @103 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 2*/ 192, // Rule ID 1 // // CHECK-NEXT: GIM_CheckSimplePredicate, GICXXPred_Simple_IsRule0Enabled, // CHECK-NEXT: // MIs[0] dst // CHECK-NEXT: // No operand predicates @@ -252,9 +250,7 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: GIM_CheckIsSafeToFold, /*InsnID*/5, // CHECK-NEXT: GIM_CheckIsSafeToFold, /*InsnID*/6, // CHECK-NEXT: GIR_MakeTempReg, /*TempRegID*/0, /*TypeID*/GILLT_s32, -// CHECK-NEXT: GIR_BuildMI, /*InsnID*/1, /*Opcode*/TargetOpcode::G_CONSTANT, -// CHECK-NEXT: GIR_AddTempRegister, /*InsnID*/1, /*TempRegID*/0, /*TempRegFlags*/0, -// CHECK-NEXT: GIR_AddCImm, /*InsnID*/1, /*Type*/GILLT_s32, /*Imm*/0, +// CHECK-NEXT: GIR_BuildConstant, /*TempRegID*/0, /*Val*/0, // CHECK-NEXT: // Combiner Rule #0: Test0 @ [a[0], b[0], c[1]] // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/TargetOpcode::COPY, // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst @@ -262,8 +258,8 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0, // CHECK-NEXT: GIR_CustomAction, GICXXCustomAction_CombineApplyGICombiner0, // CHECK-NEXT: GIR_Done, -// CHECK-NEXT: // Label 2: @208 -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 3*/ 305, // Rule ID 2 // +// CHECK-NEXT: // Label 2: @192 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 3*/ 281, // Rule ID 2 // // CHECK-NEXT: GIM_CheckSimplePredicate, GICXXPred_Simple_IsRule0Enabled, // CHECK-NEXT: // MIs[0] dst // CHECK-NEXT: // No operand predicates @@ -301,9 +297,7 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: GIM_CheckIsSafeToFold, /*InsnID*/5, // CHECK-NEXT: GIM_CheckIsSafeToFold, /*InsnID*/6, // CHECK-NEXT: GIR_MakeTempReg, /*TempRegID*/0, /*TypeID*/GILLT_s32, -// CHECK-NEXT: GIR_BuildMI, /*InsnID*/1, /*Opcode*/TargetOpcode::G_CONSTANT, -// CHECK-NEXT: GIR_AddTempRegister, /*InsnID*/1, /*TempRegID*/0, /*TempRegFlags*/0, -// CHECK-NEXT: GIR_AddCImm, /*InsnID*/1, /*Type*/GILLT_s32, /*Imm*/0, +// CHECK-NEXT: GIR_BuildConstant, /*TempRegID*/0, /*Val*/0, // CHECK-NEXT: // Combiner Rule #0: Test0 @ [a[0], b[1], c[0]] // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/TargetOpcode::COPY, // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst @@ -311,8 +305,8 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0, // CHECK-NEXT: GIR_CustomAction, GICXXCustomAction_CombineApplyGICombiner0, // CHECK-NEXT: GIR_Done, -// CHECK-NEXT: // Label 3: @305 -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 4*/ 393, // Rule ID 3 // +// CHECK-NEXT: // Label 3: @281 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 4*/ 361, // Rule ID 3 // // CHECK-NEXT: GIM_CheckSimplePredicate, GICXXPred_Simple_IsRule0Enabled, // CHECK-NEXT: // MIs[0] dst // CHECK-NEXT: // No operand predicates @@ -346,9 +340,7 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: GIM_CheckIsSafeToFold, /*InsnID*/4, // CHECK-NEXT: GIM_CheckIsSafeToFold, /*InsnID*/5, // CHECK-NEXT: GIR_MakeTempReg, /*TempRegID*/0, /*TypeID*/GILLT_s32, -// CHECK-NEXT: GIR_BuildMI, /*InsnID*/1, /*Opcode*/TargetOpcode::G_CONSTANT, -// CHECK-NEXT: GIR_AddTempRegister, /*InsnID*/1, /*TempRegID*/0, /*TempRegFlags*/0, -// CHECK-NEXT: GIR_AddCImm, /*InsnID*/1, /*Type*/GILLT_s32, /*Imm*/0, +// CHECK-NEXT: GIR_BuildConstant, /*TempRegID*/0, /*Val*/0, // CHECK-NEXT: // Combiner Rule #0: Test0 @ [a[0], b[1], c[1]] // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/TargetOpcode::COPY, // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst @@ -356,8 +348,8 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0, // CHECK-NEXT: GIR_CustomAction, GICXXCustomAction_CombineApplyGICombiner0, // CHECK-NEXT: GIR_Done, -// CHECK-NEXT: // Label 4: @393 -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 5*/ 490, // Rule ID 4 // +// CHECK-NEXT: // Label 4: @361 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 5*/ 450, // Rule ID 4 // // CHECK-NEXT: GIM_CheckSimplePredicate, GICXXPred_Simple_IsRule0Enabled, // CHECK-NEXT: // MIs[0] dst // CHECK-NEXT: // No operand predicates @@ -395,9 +387,7 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: GIM_CheckIsSafeToFold, /*InsnID*/5, // CHECK-NEXT: GIM_CheckIsSafeToFold, /*InsnID*/6, // CHECK-NEXT: GIR_MakeTempReg, /*TempRegID*/0, /*TypeID*/GILLT_s32, -// CHECK-NEXT: GIR_BuildMI, /*InsnID*/1, /*Opcode*/TargetOpcode::G_CONSTANT, -// CHECK-NEXT: GIR_AddTempRegister, /*InsnID*/1, /*TempRegID*/0, /*TempRegFlags*/0, -// CHECK-NEXT: GIR_AddCImm, /*InsnID*/1, /*Type*/GILLT_s32, /*Imm*/0, +// CHECK-NEXT: GIR_BuildConstant, /*TempRegID*/0, /*Val*/0, // CHECK-NEXT: // Combiner Rule #0: Test0 @ [a[1], b[0], c[0]] // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/TargetOpcode::COPY, // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst @@ -405,8 +395,8 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0, // CHECK-NEXT: GIR_CustomAction, GICXXCustomAction_CombineApplyGICombiner0, // CHECK-NEXT: GIR_Done, -// CHECK-NEXT: // Label 5: @490 -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 6*/ 578, // Rule ID 5 // +// CHECK-NEXT: // Label 5: @450 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 6*/ 530, // Rule ID 5 // // CHECK-NEXT: GIM_CheckSimplePredicate, GICXXPred_Simple_IsRule0Enabled, // CHECK-NEXT: // MIs[0] dst // CHECK-NEXT: // No operand predicates @@ -440,9 +430,7 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: GIM_CheckIsSafeToFold, /*InsnID*/4, // CHECK-NEXT: GIM_CheckIsSafeToFold, /*InsnID*/5, // CHECK-NEXT: GIR_MakeTempReg, /*TempRegID*/0, /*TypeID*/GILLT_s32, -// CHECK-NEXT: GIR_BuildMI, /*InsnID*/1, /*Opcode*/TargetOpcode::G_CONSTANT, -// CHECK-NEXT: GIR_AddTempRegister, /*InsnID*/1, /*TempRegID*/0, /*TempRegFlags*/0, -// CHECK-NEXT: GIR_AddCImm, /*InsnID*/1, /*Type*/GILLT_s32, /*Imm*/0, +// CHECK-NEXT: GIR_BuildConstant, /*TempRegID*/0, /*Val*/0, // CHECK-NEXT: // Combiner Rule #0: Test0 @ [a[1], b[0], c[1]] // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/TargetOpcode::COPY, // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst @@ -450,8 +438,8 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0, // CHECK-NEXT: GIR_CustomAction, GICXXCustomAction_CombineApplyGICombiner0, // CHECK-NEXT: GIR_Done, -// CHECK-NEXT: // Label 6: @578 -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 7*/ 666, // Rule ID 6 // +// CHECK-NEXT: // Label 6: @530 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 7*/ 610, // Rule ID 6 // // CHECK-NEXT: GIM_CheckSimplePredicate, GICXXPred_Simple_IsRule0Enabled, // CHECK-NEXT: // MIs[0] dst // CHECK-NEXT: // No operand predicates @@ -485,9 +473,7 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: GIM_CheckIsSafeToFold, /*InsnID*/4, // CHECK-NEXT: GIM_CheckIsSafeToFold, /*InsnID*/5, // CHECK-NEXT: GIR_MakeTempReg, /*TempRegID*/0, /*TypeID*/GILLT_s32, -// CHECK-NEXT: GIR_BuildMI, /*InsnID*/1, /*Opcode*/TargetOpcode::G_CONSTANT, -// CHECK-NEXT: GIR_AddTempRegister, /*InsnID*/1, /*TempRegID*/0, /*TempRegFlags*/0, -// CHECK-NEXT: GIR_AddCImm, /*InsnID*/1, /*Type*/GILLT_s32, /*Imm*/0, +// CHECK-NEXT: GIR_BuildConstant, /*TempRegID*/0, /*Val*/0, // CHECK-NEXT: // Combiner Rule #0: Test0 @ [a[1], b[1], c[0]] // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/TargetOpcode::COPY, // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst @@ -495,8 +481,8 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0, // CHECK-NEXT: GIR_CustomAction, GICXXCustomAction_CombineApplyGICombiner0, // CHECK-NEXT: GIR_Done, -// CHECK-NEXT: // Label 7: @666 -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 8*/ 745, // Rule ID 7 // +// CHECK-NEXT: // Label 7: @610 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 8*/ 681, // Rule ID 7 // // CHECK-NEXT: GIM_CheckSimplePredicate, GICXXPred_Simple_IsRule0Enabled, // CHECK-NEXT: // MIs[0] dst // CHECK-NEXT: // No operand predicates @@ -526,9 +512,7 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: GIM_CheckIsSafeToFold, /*InsnID*/3, // CHECK-NEXT: GIM_CheckIsSafeToFold, /*InsnID*/4, // CHECK-NEXT: GIR_MakeTempReg, /*TempRegID*/0, /*TypeID*/GILLT_s32, -// CHECK-NEXT: GIR_BuildMI, /*InsnID*/1, /*Opcode*/TargetOpcode::G_CONSTANT, -// CHECK-NEXT: GIR_AddTempRegister, /*InsnID*/1, /*TempRegID*/0, /*TempRegFlags*/0, -// CHECK-NEXT: GIR_AddCImm, /*InsnID*/1, /*Type*/GILLT_s32, /*Imm*/0, +// CHECK-NEXT: GIR_BuildConstant, /*TempRegID*/0, /*Val*/0, // CHECK-NEXT: // Combiner Rule #0: Test0 @ [a[1], b[1], c[1]] // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/TargetOpcode::COPY, // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst @@ -536,9 +520,9 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0, // CHECK-NEXT: GIR_CustomAction, GICXXCustomAction_CombineApplyGICombiner0, // CHECK-NEXT: GIR_Done, -// CHECK-NEXT: // Label 8: @745 +// CHECK-NEXT: // Label 8: @681 // CHECK-NEXT: GIM_Reject, -// CHECK-NEXT: // Label 0: @746 +// CHECK-NEXT: // Label 0: @682 // CHECK-NEXT: GIM_Reject, // CHECK-NEXT: }; // CHECK-NEXT: return MatchTable0; diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-typeof.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-typeof.td new file mode 100644 index 0000000000000..496d86aeef2d1 --- /dev/null +++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-typeof.td @@ -0,0 +1,49 @@ +// RUN: llvm-tblgen -I %p/../../../include -gen-global-isel-combiner \ +// RUN: -combiners=MyCombiner %s | \ +// RUN: FileCheck %s + +include "llvm/Target/Target.td" +include "llvm/Target/GlobalISel/Combine.td" + +def MyTargetISA : InstrInfo; +def MyTarget : Target { let InstructionSet = MyTargetISA; } + +def Test0 : GICombineRule< + (defs root:$dst), + (match (G_MUL $dst, $src, -1)), + (apply (G_SUB $dst, (GITypeOf<"$src"> 0), $tmp), + (G_CONSTANT GITypeOf<"$dst">:$tmp, (GITypeOf<"$src"> 42)))>; + +// CHECK: const int64_t *GenMyCombiner::getMatchTable() const { +// CHECK-NEXT: constexpr static int64_t MatchTable0[] = { +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 0*/ 57, // Rule ID 0 // +// CHECK-NEXT: GIM_CheckSimplePredicate, GICXXPred_Simple_IsRule0Enabled, +// CHECK-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_MUL, +// CHECK-NEXT: // MIs[0] dst +// CHECK-NEXT: GIM_RecordRegType, /*MI*/0, /*Op*/0, /*TempTypeIdx*/-1, +// CHECK-NEXT: // MIs[0] src +// CHECK-NEXT: GIM_RecordRegType, /*MI*/0, /*Op*/1, /*TempTypeIdx*/-2, +// CHECK-NEXT: // MIs[0] Operand 2 +// CHECK-NEXT: GIM_CheckConstantInt, /*MI*/0, /*Op*/2, -1, +// CHECK-NEXT: GIR_MakeTempReg, /*TempRegID*/1, /*TypeID*/-2, +// CHECK-NEXT: GIR_BuildConstant, /*TempRegID*/1, /*Val*/0, +// CHECK-NEXT: GIR_MakeTempReg, /*TempRegID*/0, /*TypeID*/-1, +// CHECK-NEXT: // Combiner Rule #0: Test0 +// CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/TargetOpcode::G_CONSTANT, +// CHECK-NEXT: GIR_AddTempRegister, /*InsnID*/0, /*TempRegID*/0, /*TempRegFlags*/0, +// CHECK-NEXT: GIR_AddCImm, /*InsnID*/0, /*Type*/-2, /*Imm*/42, +// CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0, +// CHECK-NEXT: GIR_BuildMI, /*InsnID*/1, /*Opcode*/TargetOpcode::G_SUB, +// CHECK-NEXT: GIR_Copy, /*NewInsnID*/1, /*OldInsnID*/0, /*OpIdx*/0, // dst +// CHECK-NEXT: GIR_AddTempRegister, /*InsnID*/1, /*TempRegID*/1, /*TempRegFlags*/0, +// CHECK-NEXT: GIR_AddTempRegister, /*InsnID*/1, /*TempRegID*/0, /*TempRegFlags*/0, +// CHECK-NEXT: GIR_Done, +// CHECK-NEXT: // Label 0: @57 +// CHECK-NEXT: GIM_Reject, +// CHECK-NEXT: }; +// CHECK-NEXT: return MatchTable0; +// CHECK-NEXT: } + +def MyCombiner: GICombiner<"GenMyCombiner", [ + Test0 +]>; diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table.td index 0f20e75d38a5d..a353d9b5aaf4e 100644 --- a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table.td +++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table.td @@ -93,12 +93,12 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK: bool GenMyCombiner::tryCombineAll(MachineInstr &I) const { // CHECK-NEXT: const TargetSubtargetInfo &ST = MF.getSubtarget(); // CHECK-NEXT: const PredicateBitset AvailableFeatures = getAvailableFeatures(); -// CHECK-NEXT: NewMIVector OutMIs; +// CHECK-NEXT: B.setInstrAndDebugLoc(I); // CHECK-NEXT: State.MIs.clear(); // CHECK-NEXT: State.MIs.push_back(&I); // CHECK-NEXT: MatchInfos = MatchInfosTy(); // CHECK-EMPTY: -// CHECK-NEXT: if (executeMatchTable(*this, OutMIs, State, ExecInfo, getMatchTable(), *ST.getInstrInfo(), MRI, *MRI.getTargetRegisterInfo(), *ST.getRegBankInfo(), AvailableFeatures, /*CoverageInfo*/ nullptr, &Observer)) +// CHECK-NEXT: if (executeMatchTable(*this, State, ExecInfo, B, getMatchTable(), *ST.getInstrInfo(), MRI, *MRI.getTargetRegisterInfo(), *ST.getRegBankInfo(), AvailableFeatures, /*CoverageInfo*/ nullptr)) // CHECK-NEXT: return true; // CHECK-NEXT: } // CHECK-EMPTY: @@ -111,7 +111,7 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: GICXXCustomAction_CombineApplyGICombiner1, // CHECK-NEXT: GICXXCustomAction_CombineApplyGICombiner2, // CHECK-NEXT: }; -// CHECK-NEXT: void GenMyCombiner::runCustomAction(unsigned ApplyID, const MatcherState &State, NewMIVector &OutMIs) const { +// CHECK-NEXT: void GenMyCombiner::runCustomAction(unsigned ApplyID, const MatcherState &State, ArrayRef OutMIs) const { // CHECK-NEXT: switch(ApplyID) { // CHECK-NEXT: case GICXXCustomAction_CombineApplyGICombiner0:{ // CHECK-NEXT: APPLY @@ -225,7 +225,7 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0, // CHECK-NEXT: GIR_Done, // CHECK-NEXT: // Label 8: @143 -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 9*/ 181, // Rule ID 7 // +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 9*/ 173, // Rule ID 7 // // CHECK-NEXT: GIM_CheckSimplePredicate, GICXXPred_Simple_IsRule6Enabled, // CHECK-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_ZEXT, // CHECK-NEXT: // MIs[0] dst @@ -234,16 +234,14 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: // No operand predicates // CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GICXXPred_MI_Predicate_GICombiner1, // CHECK-NEXT: GIR_MakeTempReg, /*TempRegID*/0, /*TypeID*/GILLT_s32, -// CHECK-NEXT: GIR_BuildMI, /*InsnID*/1, /*Opcode*/TargetOpcode::G_CONSTANT, -// CHECK-NEXT: GIR_AddTempRegister, /*InsnID*/1, /*TempRegID*/0, /*TempRegFlags*/0, -// CHECK-NEXT: GIR_AddCImm, /*InsnID*/1, /*Type*/GILLT_s32, /*Imm*/0, +// CHECK-NEXT: GIR_BuildConstant, /*TempRegID*/0, /*Val*/0, // CHECK-NEXT: // Combiner Rule #6: PatFragTest0 @ [__PatFragTest0_match_1[0]] // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/TargetOpcode::COPY, // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst // CHECK-NEXT: GIR_AddTempRegister, /*InsnID*/0, /*TempRegID*/0, /*TempRegFlags*/0, // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0, // CHECK-NEXT: GIR_Done, -// CHECK-NEXT: // Label 9: @181 +// CHECK-NEXT: // Label 9: @173 // CHECK-NEXT: GIM_Reject, // CHECK-NEXT: }; // CHECK-NEXT: return MatchTable0; diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/operand-types.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/operand-types.td index c871e603e4e05..4769bed972401 100644 --- a/llvm/test/TableGen/GlobalISelCombinerEmitter/operand-types.td +++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/operand-types.td @@ -79,7 +79,33 @@ def PatFragTest0 : GICombineRule< (match (FooPF $dst)), (apply (COPY $dst, (i32 0)))>; + +// CHECK: (CombineRule name:TypeOfProp id:2 root:x +// CHECK-NEXT: (MatchPats +// CHECK-NEXT: __TypeOfProp_match_0:(CodeGenInstructionPattern G_ZEXT operands:[$x, $y]) +// CHECK-NEXT: ) +// CHECK-NEXT: (ApplyPats +// CHECK-NEXT: __TypeOfProp_apply_0:(CodeGenInstructionPattern G_ANYEXT operands:[$x, GITypeOf<$y>:$tmp]) +// CHECK-NEXT: __TypeOfProp_apply_1:(CodeGenInstructionPattern G_ANYEXT operands:[GITypeOf<$y>:$tmp, $y]) +// CHECK-NEXT: ) +// CHECK-NEXT: (OperandTable MatchPats +// CHECK-NEXT: x -> __TypeOfProp_match_0 +// CHECK-NEXT: y -> +// CHECK-NEXT: ) +// CHECK-NEXT: (OperandTable ApplyPats +// CHECK-NEXT: tmp -> __TypeOfProp_apply_1 +// CHECK-NEXT: x -> __TypeOfProp_apply_0 +// CHECK-NEXT: y -> +// CHECK-NEXT: ) +// CHECK-NEXT: ) +def TypeOfProp : GICombineRule< + (defs root:$x), + (match (G_ZEXT $x, $y)), + (apply (G_ANYEXT $x, GITypeOf<"$y">:$tmp), + (G_ANYEXT $tmp, $y))>; + def MyCombiner: GICombiner<"GenMyCombiner", [ InstTest0, - PatFragTest0 + PatFragTest0, + TypeOfProp ]>; diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/pattern-parsing.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/pattern-parsing.td index bc75b15233b55..fd41a7d1d7241 100644 --- a/llvm/test/TableGen/GlobalISelCombinerEmitter/pattern-parsing.td +++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/pattern-parsing.td @@ -297,6 +297,28 @@ def VariadicsOutTest : GICombineRule< (apply (COPY $a, (i32 0)), (COPY $b, (i32 0)))>; +// CHECK: (CombineRule name:TypeOfTest id:10 root:dst +// CHECK-NEXT: (MatchPats +// CHECK-NEXT: __TypeOfTest_match_0:(CodeGenInstructionPattern COPY operands:[$dst, $tmp]) +// CHECK-NEXT: __TypeOfTest_match_1:(CodeGenInstructionPattern G_ZEXT operands:[$tmp, $src]) +// CHECK-NEXT: ) +// CHECK-NEXT: (ApplyPats +// CHECK-NEXT: __TypeOfTest_apply_0:(CodeGenInstructionPattern G_MUL operands:[$dst, (GITypeOf<$src> 0), (GITypeOf<$dst> -1)]) +// CHECK-NEXT: ) +// CHECK-NEXT: (OperandTable MatchPats +// CHECK-NEXT: dst -> __TypeOfTest_match_0 +// CHECK-NEXT: src -> +// CHECK-NEXT: tmp -> __TypeOfTest_match_1 +// CHECK-NEXT: ) +// CHECK-NEXT: (OperandTable ApplyPats +// CHECK-NEXT: dst -> __TypeOfTest_apply_0 +// CHECK-NEXT: ) +// CHECK-NEXT: ) +def TypeOfTest : GICombineRule< + (defs root:$dst), + (match (COPY $dst, $tmp), + (G_ZEXT $tmp, $src)), + (apply (G_MUL $dst, (GITypeOf<"$src"> 0), (GITypeOf<"$dst"> -1)))>; def MyCombiner: GICombiner<"GenMyCombiner", [ WipOpcodeTest0, @@ -308,5 +330,6 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ PatFragTest0, PatFragTest1, VariadicsInTest, - VariadicsOutTest + VariadicsOutTest, + TypeOfTest ]>; diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/typeof-errors.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/typeof-errors.td new file mode 100644 index 0000000000000..6040d6def4497 --- /dev/null +++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/typeof-errors.td @@ -0,0 +1,72 @@ +// RUN: not llvm-tblgen -I %p/../../../include -gen-global-isel-combiner \ +// RUN: -combiners=MyCombiner %s 2>&1| \ +// RUN: FileCheck %s -implicit-check-not=error: + +include "llvm/Target/Target.td" +include "llvm/Target/GlobalISel/Combine.td" + +def MyTargetISA : InstrInfo; +def MyTarget : Target { let InstructionSet = MyTargetISA; } + +// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: invalid operand name format 'unknown' in GITypeOf: expected '$' followed by an operand name +def NoDollarSign : GICombineRule< + (defs root:$dst), + (match (G_ZEXT $dst, $src)), + (apply (G_ANYEXT $dst, (GITypeOf<"unknown"> 0)))>; + +// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: 'unknown' ('GITypeOf<$unknown>') does not refer to a matched operand! +def UnknownOperand : GICombineRule< + (defs root:$dst), + (match (G_ZEXT $dst, $src)), + (apply (G_ANYEXT $dst, (GITypeOf<"$unknown"> 0)))>; + +// CHECK: :[[@LINE+2]]:{{[0-9]+}}: error: GISpecialType is not supported in 'match' patterns +// CHECK: :[[@LINE+1]]:{{[0-9]+}}: note: operand 1 of '__UseInMatch_match_0' has type 'GITypeOf<$dst>' +def UseInMatch : GICombineRule< + (defs root:$dst), + (match (G_ZEXT $dst, (GITypeOf<"$dst"> 0))), + (apply (G_ANYEXT $dst, (i32 0)))>; + +// CHECK: :[[@LINE+3]]:{{[0-9]+}}: error: GISpecialType is not supported in GICombinePatFrag +// CHECK: :[[@LINE+2]]:{{[0-9]+}}: note: operand 1 of '__PFWithTypeOF_alt0_pattern_0' has type 'GITypeOf<$dst> +// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: Could not parse GICombinePatFrag 'PFWithTypeOF' +def PFWithTypeOF: GICombinePatFrag< + (outs $dst), (ins), + [(pattern (G_ANYEXT $dst, (GITypeOf<"$dst"> 0)))]>; + +// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: Failed to parse pattern: '(PFWithTypeOF ?:$dst)' +def UseInPF: GICombineRule< + (defs root:$dst), + (match (PFWithTypeOF $dst)), + (apply (G_ANYEXT $dst, (i32 0)))>; + +// CHECK: :[[@LINE+2]]:{{[0-9]+}}: error: GISpecialType is not supported in 'match' patterns +// CHECK: :[[@LINE+1]]:{{[0-9]+}}: note: operand 1 of '__InferredUseInMatch_match_0' has type 'GITypeOf<$dst>' +def InferredUseInMatch : GICombineRule< + (defs root:$dst), + (match (G_ZEXT $dst, $src)), + (apply (G_ANYEXT $dst, GITypeOf<"$dst">:$src))>; + +// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: conflicting types for operand 'src': first seen with 'i32' in '__InferenceConflict_match_0, now seen with 'GITypeOf<$dst>' in '__InferenceConflict_apply_0' +def InferenceConflict : GICombineRule< + (defs root:$dst), + (match (G_ZEXT $dst, i32:$src)), + (apply (G_ANYEXT $dst, GITypeOf<"$dst">:$src))>; + +// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: 'tmp' ('GITypeOf<$tmp>') does not refer to a matched operand! +def TypeOfApplyTmp : GICombineRule< + (defs root:$dst), + (match (G_ZEXT $dst, $src)), + (apply (G_ANYEXT $dst, i32:$tmp), + (G_ANYEXT $tmp, (GITypeOf<"$tmp"> 0)))>; + +// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: Failed to parse one or more rules +def MyCombiner: GICombiner<"GenMyCombiner", [ + NoDollarSign, + UnknownOperand, + UseInMatch, + UseInPF, + InferredUseInMatch, + InferenceConflict, + TypeOfApplyTmp +]>; diff --git a/llvm/test/TableGen/GlobalISelEmitter.td b/llvm/test/TableGen/GlobalISelEmitter.td index 7cca2d52e4062..70602c8fa3ded 100644 --- a/llvm/test/TableGen/GlobalISelEmitter.td +++ b/llvm/test/TableGen/GlobalISelEmitter.td @@ -82,7 +82,7 @@ def HasC : Predicate<"Subtarget->hasC()"> { let RecomputePerFunction = 1; } // CHECK-NEXT: const int64_t *getMatchTable() const override; // CHECK-NEXT: bool testMIPredicate_MI(unsigned PredicateID, const MachineInstr &MI, const MatcherState &State) const override; // CHECK-NEXT: bool testSimplePredicate(unsigned PredicateID) const override; -// CHECK-NEXT: void runCustomAction(unsigned FnID, const MatcherState &State, NewMIVector &OutMIs) const override; +// CHECK-NEXT: void runCustomAction(unsigned FnID, const MatcherState &State, ArrayRef OutMIs) const override; // CHECK-NEXT: #endif // ifdef GET_GLOBALISEL_TEMPORARIES_DECL // CHECK-LABEL: #ifdef GET_GLOBALISEL_TEMPORARIES_INIT @@ -216,11 +216,11 @@ def HasC : Predicate<"Subtarget->hasC()"> { let RecomputePerFunction = 1; } // CHECK: bool MyTargetInstructionSelector::selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const { // CHECK-NEXT: const PredicateBitset AvailableFeatures = getAvailableFeatures(); -// CHECK-NEXT: NewMIVector OutMIs; +// CHECK-NEXT: MachineIRBuilder B(I); // CHECK-NEXT: State.MIs.clear(); // CHECK-NEXT: State.MIs.push_back(&I); -// CHECK: if (executeMatchTable(*this, OutMIs, State, ExecInfo, getMatchTable(), TII, MF->getRegInfo(), TRI, RBI, AvailableFeatures, &CoverageInfo)) { +// CHECK: if (executeMatchTable(*this, State, ExecInfo, B, getMatchTable(), TII, MF->getRegInfo(), TRI, RBI, AvailableFeatures, &CoverageInfo)) { // CHECK-NEXT: return true; // CHECK-NEXT: } diff --git a/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp b/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp index 08a4db2fb3dec..cfc891e80f7fd 100644 --- a/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp +++ b/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp @@ -73,6 +73,8 @@ constexpr StringLiteral CXXApplyPrefix = "GICXXCustomAction_CombineApply"; constexpr StringLiteral CXXPredPrefix = "GICXXPred_MI_Predicate_"; constexpr StringLiteral PatFragClassName = "GICombinePatFrag"; constexpr StringLiteral BuiltinInstClassName = "GIBuiltinInst"; +constexpr StringLiteral SpecialTyClassName = "GISpecialType"; +constexpr StringLiteral TypeOfClassName = "GITypeOf"; std::string getIsEnabledPredicateEnumName(unsigned CombinerRuleID) { return "GICXXPred_Simple_IsRule" + to_string(CombinerRuleID) + "Enabled"; @@ -123,11 +125,6 @@ template auto values(Container &&C) { return map_range(C, [](auto &Entry) -> auto & { return Entry.second; }); } -LLTCodeGen getLLTCodeGenFromRecord(const Record *Ty) { - assert(Ty->isSubClassOf("ValueType")); - return LLTCodeGen(*MVTToLLT(getValueType(Ty))); -} - //===- MatchData Handling -------------------------------------------------===// /// Represents MatchData defined by the match stage and required by the apply @@ -292,6 +289,117 @@ class CXXPredicateCode { CXXPredicateCode::CXXPredicateCodePool CXXPredicateCode::AllCXXMatchCode; CXXPredicateCode::CXXPredicateCodePool CXXPredicateCode::AllCXXApplyCode; +//===- PatternType --------------------------------------------------------===// + +/// Simple wrapper around a Record* of a type. +/// +/// Types have two form: +/// - LLTs, which are straightforward. +/// - Special types, e.g. GITypeOf +class PatternType { +public: + PatternType() = default; + PatternType(const Record *R) : R(R) {} + + bool isValidType() const { return !R || isLLT() || isSpecial(); } + + bool isLLT() const { return R && R->isSubClassOf("ValueType"); } + bool isSpecial() const { return R && R->isSubClassOf(SpecialTyClassName); } + bool isTypeOf() const { return R && R->isSubClassOf(TypeOfClassName); } + + StringRef getTypeOfOpName() const; + LLTCodeGen getLLTCodeGen() const; + + bool checkSemantics(ArrayRef DiagLoc) const; + + LLTCodeGenOrTempType getLLTCodeGenOrTempType(RuleMatcher &RM) const; + + explicit operator bool() const { return R != nullptr; } + + bool operator==(const PatternType &Other) const; + bool operator!=(const PatternType &Other) const { return !operator==(Other); } + + std::string str() const; + +private: + StringRef getRawOpName() const { return R->getValueAsString("OpName"); } + + const Record *R = nullptr; +}; + +StringRef PatternType::getTypeOfOpName() const { + assert(isTypeOf()); + StringRef Name = getRawOpName(); + Name.consume_front("$"); + return Name; +} + +LLTCodeGen PatternType::getLLTCodeGen() const { + assert(isLLT()); + return *MVTToLLT(getValueType(R)); +} + +LLTCodeGenOrTempType +PatternType::getLLTCodeGenOrTempType(RuleMatcher &RM) const { + assert(isValidType()); + + if (isLLT()) + return getLLTCodeGen(); + + assert(isTypeOf()); + auto &OM = RM.getOperandMatcher(getTypeOfOpName()); + return OM.getTempTypeIdx(RM); +} + +bool PatternType::checkSemantics(ArrayRef DiagLoc) const { + if (!isTypeOf()) + return true; + + auto RawOpName = getRawOpName(); + if (RawOpName.starts_with("$")) + return true; + + PrintError(DiagLoc, "invalid operand name format '" + RawOpName + "' in " + + TypeOfClassName + + ": expected '$' followed by an operand name"); + return false; +} + +bool PatternType::operator==(const PatternType &Other) const { + if (R == Other.R) { + if (R && R->getName() != Other.R->getName()) { + dbgs() << "Same ptr but: " << R->getName() << " and " + << Other.R->getName() << "?\n"; + assert(false); + } + return true; + } + + if (isTypeOf() && Other.isTypeOf()) + return getTypeOfOpName() == Other.getTypeOfOpName(); + + return false; +} + +std::string PatternType::str() const { + if (!R) + return ""; + + if (!isValidType()) + return ""; + + if (isLLT()) + return R->getName().str(); + + assert(isSpecial()); + + // TODO: Use an enum for these? + if (isTypeOf()) + return (TypeOfClassName + "<$" + getTypeOfOpName() + ">").str(); + + llvm_unreachable("Unknown type!"); +} + //===- Pattern Base Class -------------------------------------------------===// /// Base class for all patterns that can be written in an `apply`, `match` or @@ -499,13 +607,15 @@ class InstructionOperand { public: using IntImmTy = int64_t; - InstructionOperand(IntImmTy Imm, StringRef Name, const Record *Type) + InstructionOperand(IntImmTy Imm, StringRef Name, PatternType Type) : Value(Imm), Name(insertStrRef(Name)), Type(Type) { - assert(!Type || Type->isSubClassOf("ValueType")); + assert(Type.isValidType()); } - InstructionOperand(StringRef Name, const Record *Type) - : Name(insertStrRef(Name)), Type(Type) {} + InstructionOperand(StringRef Name, PatternType Type) + : Name(insertStrRef(Name)), Type(Type) { + assert(Type.isValidType()); + } bool isNamedImmediate() const { return hasImmValue() && isNamedOperand(); } @@ -527,11 +637,12 @@ class InstructionOperand { void setIsDef(bool Value = true) { Def = Value; } bool isDef() const { return Def; } - void setType(const Record *R) { - assert((!Type || (Type == R)) && "Overwriting type!"); - Type = R; + void setType(PatternType NewType) { + assert((!Type || (Type == NewType)) && "Overwriting type!"); + assert(NewType.isValidType()); + Type = NewType; } - const Record *getType() const { return Type; } + PatternType getType() const { return Type; } std::string describe() const { if (!hasImmValue()) @@ -547,11 +658,11 @@ class InstructionOperand { OS << ""; bool NeedsColon = true; - if (const Record *Ty = getType()) { + if (Type) { if (hasImmValue()) - OS << "(" << Ty->getName() << " " << getImmValue() << ")"; + OS << "(" << Type.str() << " " << getImmValue() << ")"; else - OS << Ty->getName(); + OS << Type.str(); } else if (hasImmValue()) OS << getImmValue(); else @@ -566,7 +677,7 @@ class InstructionOperand { private: std::optional Value; StringRef Name; - const Record *Type = nullptr; + PatternType Type; bool Def = false; }; @@ -622,6 +733,10 @@ class InstructionPattern : public Pattern { virtual StringRef getInstName() const = 0; + /// Diagnoses all uses of special types in this Pattern and returns true if at + /// least one diagnostic was emitted. + bool diagnoseAllSpecialTypes(ArrayRef Loc, Twine Msg) const; + void reportUnreachable(ArrayRef Locs) const; virtual bool checkSemantics(ArrayRef Loc); @@ -633,6 +748,20 @@ class InstructionPattern : public Pattern { SmallVector Operands; }; +bool InstructionPattern::diagnoseAllSpecialTypes(ArrayRef Loc, + Twine Msg) const { + bool HasDiag = false; + for (const auto &[Idx, Op] : enumerate(operands())) { + if (Op.getType().isSpecial()) { + PrintError(Loc, Msg); + PrintNote(Loc, "operand " + Twine(Idx) + " of '" + getName() + + "' has type '" + Op.getType().str() + "'"); + HasDiag = true; + } + } + return HasDiag; +} + void InstructionPattern::reportUnreachable(ArrayRef Locs) const { PrintError(Locs, "pattern '" + getName() + "' ('" + getInstName() + "') is unreachable from the pattern root!"); @@ -829,17 +958,20 @@ unsigned CodeGenInstructionPattern::getNumInstOperands() const { /// It infers the type of each operand, check it's consistent with the known /// type of the operand, and then sets all of the types in all operands in /// setAllOperandTypes. +/// +/// It also handles verifying correctness of special types. class OperandTypeChecker { public: OperandTypeChecker(ArrayRef DiagLoc) : DiagLoc(DiagLoc) {} - bool check(InstructionPattern *P); + bool check(InstructionPattern *P, + std::function VerifyTypeOfOperand); void setAllOperandTypes(); private: struct OpTypeInfo { - const Record *Type = nullptr; + PatternType Type; InstructionPattern *TypeSrc = nullptr; }; @@ -849,16 +981,26 @@ class OperandTypeChecker { SmallVector Pats; }; -bool OperandTypeChecker::check(InstructionPattern *P) { +bool OperandTypeChecker::check( + InstructionPattern *P, + std::function VerifyTypeOfOperand) { Pats.push_back(P); - for (auto &Op : P->named_operands()) { - const Record *Ty = Op.getType(); + for (auto &Op : P->operands()) { + const auto Ty = Op.getType(); if (!Ty) continue; - auto &Info = Types[Op.getOperandName()]; + if (!Ty.checkSemantics(DiagLoc)) + return false; + + if (Ty.isTypeOf() && !VerifyTypeOfOperand(Ty)) + return false; + if (!Op.isNamedOperand()) + continue; + + auto &Info = Types[Op.getOperandName()]; if (!Info.Type) { Info.Type = Ty; Info.TypeSrc = P; @@ -868,9 +1010,9 @@ bool OperandTypeChecker::check(InstructionPattern *P) { if (Info.Type != Ty) { PrintError(DiagLoc, "conflicting types for operand '" + Op.getOperandName() + "': first seen with '" + - Info.Type->getName() + "' in '" + + Info.Type.str() + "' in '" + Info.TypeSrc->getName() + ", now seen with '" + - Ty->getName() + "' in '" + P->getName() + "'"); + Ty.str() + "' in '" + P->getName() + "'"); return false; } } @@ -1058,7 +1200,12 @@ bool PatFrag::checkSemantics() { PatFragClassName); return false; case Pattern::K_CXX: + continue; case Pattern::K_CodeGenInstruction: + if (cast(Pat.get())->diagnoseAllSpecialTypes( + Def.getLoc(), SpecialTyClassName + " is not supported in " + + PatFragClassName)) + return false; continue; case Pattern::K_PatFrag: // TODO: It's just that the emitter doesn't handle it but technically @@ -1142,12 +1289,16 @@ bool PatFrag::checkSemantics() { // TODO: find unused params + const auto CheckTypeOf = [&](const PatternType &) -> bool { + llvm_unreachable("GITypeOf should have been rejected earlier!"); + }; + // Now, typecheck all alternatives. for (auto &Alt : Alts) { OperandTypeChecker OTC(Def.getLoc()); for (auto &Pat : Alt.Pats) { if (auto *IP = dyn_cast(Pat.get())) { - if (!OTC.check(IP)) + if (!OTC.check(IP, CheckTypeOf)) return false; } } @@ -1954,21 +2105,48 @@ bool CombineRuleBuilder::hasEraseRoot() const { bool CombineRuleBuilder::typecheckPatterns() { OperandTypeChecker OTC(RuleDef.getLoc()); + const auto CheckMatchTypeOf = [&](const PatternType &) -> bool { + // We'll reject those after we're done inferring + return true; + }; + for (auto &Pat : values(MatchPats)) { if (auto *IP = dyn_cast(Pat.get())) { - if (!OTC.check(IP)) + if (!OTC.check(IP, CheckMatchTypeOf)) return false; } } + const auto CheckApplyTypeOf = [&](const PatternType &Ty) { + // GITypeOf<"$x"> can only be used if "$x" is a matched operand. + const auto OpName = Ty.getTypeOfOpName(); + if (MatchOpTable.lookup(OpName).Found) + return true; + + PrintError("'" + OpName + "' ('" + Ty.str() + + "') does not refer to a matched operand!"); + return false; + }; + for (auto &Pat : values(ApplyPats)) { if (auto *IP = dyn_cast(Pat.get())) { - if (!OTC.check(IP)) + if (!OTC.check(IP, CheckApplyTypeOf)) return false; } } OTC.setAllOperandTypes(); + + // Always check this after in case inference adds some special types to the match patterns. + for (auto &Pat : values(MatchPats)) { + if (auto *IP = dyn_cast(Pat.get())) { + if (IP->diagnoseAllSpecialTypes( + RuleDef.getLoc(), + SpecialTyClassName + " is not supported in 'match' patterns")) { + return false; + } + } + } return true; } @@ -2461,10 +2639,12 @@ bool CombineRuleBuilder::parseInstructionPatternOperand( if (DagOp->getNumArgs() != 1) return ParseErr(); - Record *ImmTy = DagOp->getOperatorAsDef(RuleDef.getLoc()); - if (!ImmTy->isSubClassOf("ValueType")) { + const Record *TyDef = DagOp->getOperatorAsDef(RuleDef.getLoc()); + PatternType ImmTy(TyDef); + if (!ImmTy.isValidType()) { PrintError("cannot parse immediate '" + OpInit->getAsUnquotedString() + - "', '" + ImmTy->getName() + "' is not a ValueType!"); + "', '" + TyDef->getName() + "' is not a ValueType or " + + SpecialTyClassName); return false; } @@ -2491,12 +2671,13 @@ bool CombineRuleBuilder::parseInstructionPatternOperand( return false; } const Record *Def = DefI->getDef(); - if (!Def->isSubClassOf("ValueType")) { + PatternType Ty(Def); + if (!Ty.isValidType()) { PrintError("invalid operand type: '" + Def->getName() + "' is not a ValueType"); return false; } - IP.addOperand(OpName->getAsUnquotedString(), Def); + IP.addOperand(OpName->getAsUnquotedString(), Ty); return true; } @@ -2823,8 +3004,8 @@ bool CombineRuleBuilder::emitPatFragMatchPattern( StringRef PFName = PF.getName(); PrintWarning("impossible type constraints: operand " + Twine(PIdx) + " of '" + PFP.getName() + "' has type '" + - ArgOp.getType()->getName() + "', but '" + PFName + - "' constrains it to '" + O.getType()->getName() + "'"); + ArgOp.getType().str() + "', but '" + PFName + + "' constrains it to '" + O.getType().str() + "'"); if (ArgOp.isNamedOperand()) PrintNote("operand " + Twine(PIdx) + " of '" + PFP.getName() + "' is '" + ArgOp.getOperandName() + "'"); @@ -3055,17 +3236,18 @@ bool CombineRuleBuilder::emitInstructionApplyPattern( // This is a brand new register. TempRegID = M.allocateTempRegID(); OperandToTempRegID[OpName] = TempRegID; - const Record *Ty = Op.getType(); + const auto Ty = Op.getType(); if (!Ty) { PrintError("def of a new register '" + OpName + "' in the apply patterns must have a type"); return false; } + declareTempRegExpansion(CE, TempRegID, OpName); // Always insert the action at the beginning, otherwise we may end up // using the temp reg before it's available. M.insertAction( - M.actions_begin(), getLLTCodeGenFromRecord(Ty), TempRegID); + M.actions_begin(), Ty.getLLTCodeGenOrTempType(M), TempRegID); } DstMI.addRenderer(TempRegID); @@ -3088,7 +3270,7 @@ bool CombineRuleBuilder::emitCodeGenInstructionApplyImmOperand( // G_CONSTANT is a special case and needs a CImm though so this is likely a // mistake. const bool isGConstant = P.is("G_CONSTANT"); - const Record *Ty = O.getType(); + const auto Ty = O.getType(); if (!Ty) { if (isGConstant) { PrintError("'G_CONSTANT' immediate must be typed!"); @@ -3101,20 +3283,18 @@ bool CombineRuleBuilder::emitCodeGenInstructionApplyImmOperand( return true; } - LLTCodeGen LLT = getLLTCodeGenFromRecord(Ty); + auto ImmTy = Ty.getLLTCodeGenOrTempType(M); + if (isGConstant) { - DstMI.addRenderer(O.getImmValue(), LLT); + DstMI.addRenderer(O.getImmValue(), ImmTy); return true; } unsigned TempRegID = M.allocateTempRegID(); - auto ActIt = M.insertAction( - M.actions_begin(), M.allocateOutputInsnID(), &getGConstant()); - // Ensure MakeTempReg occurs before the BuildMI of th G_CONSTANT. - M.insertAction(ActIt, LLT, TempRegID); - auto &ConstantMI = *static_cast(ActIt->get()); - ConstantMI.addRenderer(TempRegID); - ConstantMI.addRenderer(O.getImmValue(), LLT); + // Ensure MakeTempReg & the BuildConstantAction occur at the beginning. + auto InsertIt = M.insertAction(M.actions_begin(), + ImmTy, TempRegID); + M.insertAction(++InsertIt, TempRegID, O.getImmValue()); DstMI.addRenderer(TempRegID); return true; } @@ -3230,8 +3410,14 @@ bool CombineRuleBuilder::emitCodeGenInstructionMatchPattern( // Always emit a check for unnamed operands. if (OpName.empty() || !M.getOperandMatcher(OpName).contains()) { - if (const Record *Ty = RemappedO.getType()) - OM.addPredicate(getLLTCodeGenFromRecord(Ty)); + if (const auto Ty = RemappedO.getType()) { + // TODO: We could support GITypeOf here on the condition that the + // OperandMatcher exists already. Though it's clunky to make this work + // and isn't all that useful so it's just rejected in typecheckPatterns + // at this time. + assert(Ty.isLLT() && "Only LLTs are supported in match patterns!"); + OM.addPredicate(Ty.getLLTCodeGen()); + } } // Stop here if the operand is a def, or if it had no name. @@ -3465,15 +3651,15 @@ void GICombinerEmitter::emitAdditionalImpl(raw_ostream &OS) { << " const TargetSubtargetInfo &ST = MF.getSubtarget();\n" << " const PredicateBitset AvailableFeatures = " "getAvailableFeatures();\n" - << " NewMIVector OutMIs;\n" + << " B.setInstrAndDebugLoc(I);\n" << " State.MIs.clear();\n" << " State.MIs.push_back(&I);\n" << " " << MatchDataInfo::StructName << " = " << MatchDataInfo::StructTypeName << "();\n\n" - << " if (executeMatchTable(*this, OutMIs, State, ExecInfo" + << " if (executeMatchTable(*this, State, ExecInfo, B" << ", getMatchTable(), *ST.getInstrInfo(), MRI, " "*MRI.getTargetRegisterInfo(), *ST.getRegBankInfo(), AvailableFeatures" - << ", /*CoverageInfo*/ nullptr, &Observer)) {\n" + << ", /*CoverageInfo*/ nullptr)) {\n" << " return true;\n" << " }\n\n" << " return false;\n" @@ -3550,7 +3736,7 @@ void GICombinerEmitter::emitRunCustomAction(raw_ostream &OS) { OS << "void " << getClassName() << "::runCustomAction(unsigned ApplyID, const MatcherState &State, " - "NewMIVector &OutMIs) const " + "ArrayRef OutMIs) const " "{\n"; if (!ApplyCode.empty()) { OS << " switch(ApplyID) {\n"; diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp index 1dbd821f20fdc..fa682620ed2f7 100644 --- a/llvm/utils/TableGen/GlobalISelEmitter.cpp +++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp @@ -2263,10 +2263,10 @@ void GlobalISelEmitter::emitAdditionalImpl(raw_ostream &OS) { "&CoverageInfo) const {\n" << " const PredicateBitset AvailableFeatures = " "getAvailableFeatures();\n" - << " NewMIVector OutMIs;\n" + << " MachineIRBuilder B(I);\n" << " State.MIs.clear();\n" << " State.MIs.push_back(&I);\n\n" - << " if (executeMatchTable(*this, OutMIs, State, ExecInfo" + << " if (executeMatchTable(*this, State, ExecInfo, B" << ", getMatchTable(), TII, MF->getRegInfo(), TRI, RBI, AvailableFeatures" << ", &CoverageInfo)) {\n" << " return true;\n" @@ -2348,7 +2348,8 @@ void GlobalISelEmitter::emitTestSimplePredicate(raw_ostream &OS) { void GlobalISelEmitter::emitRunCustomAction(raw_ostream &OS) { OS << "void " << getClassName() - << "::runCustomAction(unsigned, const MatcherState&, NewMIVector &) const " + << "::runCustomAction(unsigned, const MatcherState&, " + "ArrayRef) const " "{\n" << " llvm_unreachable(\"" + getClassName() + " does not support custom C++ actions!\");\n" diff --git a/llvm/utils/TableGen/GlobalISelMatchTable.cpp b/llvm/utils/TableGen/GlobalISelMatchTable.cpp index dcfd0a34beb07..f6e9240a322fc 100644 --- a/llvm/utils/TableGen/GlobalISelMatchTable.cpp +++ b/llvm/utils/TableGen/GlobalISelMatchTable.cpp @@ -822,6 +822,15 @@ const OperandMatcher &RuleMatcher::getPhysRegOperandMatcher(Record *Reg) const { return *I->second; } +OperandMatcher &RuleMatcher::getOperandMatcher(StringRef Name) { + const auto &I = DefinedOperands.find(Name); + + if (I == DefinedOperands.end()) + PrintFatalError(SrcLoc, "Operand " + Name + " was not declared in matcher"); + + return *I->second; +} + const OperandMatcher &RuleMatcher::getOperandMatcher(StringRef Name) const { const auto &I = DefinedOperands.find(Name); @@ -1081,6 +1090,17 @@ void RecordNamedOperandMatcher::emitPredicateOpcodes(MatchTable &Table, << MatchTable::Comment("Name : " + Name) << MatchTable::LineBreak; } +//===- RecordRegisterType ------------------------------------------===// + +void RecordRegisterType::emitPredicateOpcodes(MatchTable &Table, + RuleMatcher &Rule) const { + assert(Idx < 0 && "Temp types always have negative indexes!"); + Table << MatchTable::Opcode("GIM_RecordRegType") << MatchTable::Comment("MI") + << MatchTable::IntValue(InsnVarID) << MatchTable::Comment("Op") + << MatchTable::IntValue(OpIdx) << MatchTable::Comment("TempTypeIdx") + << MatchTable::IntValue(Idx) << MatchTable::LineBreak; +} + //===- ComplexPatternOperandMatcher ---------------------------------------===// void ComplexPatternOperandMatcher::emitPredicateOpcodes( @@ -1196,6 +1216,17 @@ std::string OperandMatcher::getOperandExpr(unsigned InsnVarID) const { unsigned OperandMatcher::getInsnVarID() const { return Insn.getInsnVarID(); } +TempTypeIdx OperandMatcher::getTempTypeIdx(RuleMatcher &Rule) { + if(TTIdx >= 0) { + // Temp type index not assigned yet, so assign one and add the necessary predicate. + TTIdx = Rule.getNextTempTypeIdx(); + assert(TTIdx < 0); + addPredicate(TTIdx); + return TTIdx; + } + return TTIdx; +} + void OperandMatcher::emitPredicateOpcodes(MatchTable &Table, RuleMatcher &Rule) { if (!Optimized) { @@ -2014,6 +2045,16 @@ void BuildMIAction::emitActionOpcodes(MatchTable &Table, EraseInstAction::emitActionOpcodes(Table, Rule, /*InsnID*/ 0); } +//===- BuildConstantAction ------------------------------------------------===// + +void BuildConstantAction::emitActionOpcodes(MatchTable &Table, + RuleMatcher &Rule) const { + Table << MatchTable::Opcode("GIR_BuildConstant") + << MatchTable::Comment("TempRegID") << MatchTable::IntValue(TempRegID) + << MatchTable::Comment("Val") << MatchTable::IntValue(Val) + << MatchTable::LineBreak; +} + //===- EraseInstAction ----------------------------------------------------===// void EraseInstAction::emitActionOpcodes(MatchTable &Table, RuleMatcher &Rule, @@ -2082,9 +2123,7 @@ void MakeTempRegisterAction::emitActionOpcodes(MatchTable &Table, RuleMatcher &Rule) const { Table << MatchTable::Opcode("GIR_MakeTempReg") << MatchTable::Comment("TempRegID") << MatchTable::IntValue(TempRegID) - << MatchTable::Comment("TypeID") - << MatchTable::NamedValue(Ty.getCxxEnumValue()) - << MatchTable::LineBreak; + << MatchTable::Comment("TypeID") << Ty << MatchTable::LineBreak; } } // namespace gi diff --git a/llvm/utils/TableGen/GlobalISelMatchTable.h b/llvm/utils/TableGen/GlobalISelMatchTable.h index 549d7ccde18bd..364f2a1ec725d 100644 --- a/llvm/utils/TableGen/GlobalISelMatchTable.h +++ b/llvm/utils/TableGen/GlobalISelMatchTable.h @@ -273,6 +273,40 @@ extern std::set KnownTypes; /// MVTs that don't map cleanly to an LLT (e.g., iPTR, *any, ...). std::optional MVTToLLT(MVT::SimpleValueType SVT); +using TempTypeIdx = int64_t; +class LLTCodeGenOrTempType { +public: + LLTCodeGenOrTempType(const LLTCodeGen &LLT) : Data(LLT) {} + LLTCodeGenOrTempType(TempTypeIdx TempTy) : Data(TempTy) {} + + bool isLLTCodeGen() const { return std::holds_alternative(Data); } + bool isTempTypeIdx() const { + return std::holds_alternative(Data); + } + + const LLTCodeGen &getLLTCodeGen() const { + assert(isLLTCodeGen()); + return std::get(Data); + } + + TempTypeIdx getTempTypeIdx() const { + assert(isTempTypeIdx()); + return std::get(Data); + } + +private: + std::variant Data; +}; + +inline MatchTable &operator<<(MatchTable &Table, + const LLTCodeGenOrTempType &Ty) { + if (Ty.isLLTCodeGen()) + Table << MatchTable::NamedValue(Ty.getLLTCodeGen().getCxxEnumValue()); + else + Table << MatchTable::IntValue(Ty.getTempTypeIdx()); + return Table; +} + //===- Matchers -----------------------------------------------------------===// class Matcher { public: @@ -459,6 +493,9 @@ class RuleMatcher : public Matcher { /// ID for the next temporary register ID allocated with allocateTempRegID() unsigned NextTempRegID; + /// ID for the next recorded type. Starts at -1 and counts down. + TempTypeIdx NextTempTypeIdx = -1; + // HwMode predicate index for this rule. -1 if no HwMode. int HwModeIdx = -1; @@ -498,6 +535,8 @@ class RuleMatcher : public Matcher { RuleMatcher(RuleMatcher &&Other) = default; RuleMatcher &operator=(RuleMatcher &&Other) = default; + TempTypeIdx getNextTempTypeIdx() { return NextTempTypeIdx--; } + uint64_t getRuleID() const { return RuleID; } InstructionMatcher &addInstructionMatcher(StringRef SymbolicName); @@ -602,6 +641,7 @@ class RuleMatcher : public Matcher { } InstructionMatcher &getInstructionMatcher(StringRef SymbolicName) const; + OperandMatcher &getOperandMatcher(StringRef Name); const OperandMatcher &getOperandMatcher(StringRef Name) const; const OperandMatcher &getPhysRegOperandMatcher(Record *) const; @@ -762,6 +802,7 @@ class PredicateMatcher { OPM_RegBank, OPM_MBB, OPM_RecordNamedOperand, + OPM_RecordRegType, }; protected: @@ -963,6 +1004,30 @@ class RecordNamedOperandMatcher : public OperandPredicateMatcher { RuleMatcher &Rule) const override; }; +/// Generates code to store a register operand's type into the set of temporary +/// LLTs. +class RecordRegisterType : public OperandPredicateMatcher { +protected: + TempTypeIdx Idx; + +public: + RecordRegisterType(unsigned InsnVarID, unsigned OpIdx, TempTypeIdx Idx) + : OperandPredicateMatcher(OPM_RecordRegType, InsnVarID, OpIdx), Idx(Idx) { + } + + static bool classof(const PredicateMatcher *P) { + return P->getKind() == OPM_RecordRegType; + } + + bool isIdentical(const PredicateMatcher &B) const override { + return OperandPredicateMatcher::isIdentical(B) && + Idx == cast(&B)->Idx; + } + + void emitPredicateOpcodes(MatchTable &Table, + RuleMatcher &Rule) const override; +}; + /// Generates code to check that an operand is a particular target constant. class ComplexPatternOperandMatcher : public OperandPredicateMatcher { protected: @@ -1169,6 +1234,8 @@ class OperandMatcher : public PredicateListMatcher { /// countRendererFns(). unsigned AllocatedTemporariesBaseID; + TempTypeIdx TTIdx = 0; + public: OperandMatcher(InstructionMatcher &Insn, unsigned OpIdx, const std::string &SymbolicName, @@ -1196,6 +1263,11 @@ class OperandMatcher : public PredicateListMatcher { unsigned getOpIdx() const { return OpIdx; } unsigned getInsnVarID() const; + /// If this OperandMatcher has not been assigned a TempTypeIdx yet, assigns it + /// one and adds a `RecordRegisterType` predicate to this matcher. If one has + /// already been assigned, simply returns it. + TempTypeIdx getTempTypeIdx(RuleMatcher &Rule); + std::string getOperandExpr(unsigned InsnVarID) const; InstructionMatcher &getInstructionMatcher() const { return Insn; } @@ -1955,15 +2027,16 @@ class ImmRenderer : public OperandRenderer { protected: unsigned InsnID; int64_t Imm; - std::optional CImmLLT; + std::optional CImmLLT; public: ImmRenderer(unsigned InsnID, int64_t Imm) : OperandRenderer(OR_Imm), InsnID(InsnID), Imm(Imm) {} - ImmRenderer(unsigned InsnID, int64_t Imm, const LLTCodeGen &CImmLLT) + ImmRenderer(unsigned InsnID, int64_t Imm, const LLTCodeGenOrTempType &CImmLLT) : OperandRenderer(OR_Imm), InsnID(InsnID), Imm(Imm), CImmLLT(CImmLLT) { - KnownTypes.insert(CImmLLT); + if (CImmLLT.isLLTCodeGen()) + KnownTypes.insert(CImmLLT.getLLTCodeGen()); } static bool classof(const OperandRenderer *R) { @@ -1976,8 +2049,7 @@ class ImmRenderer : public OperandRenderer { "ConstantInt immediate are only for combiners!"); Table << MatchTable::Opcode("GIR_AddCImm") << MatchTable::Comment("InsnID") << MatchTable::IntValue(InsnID) - << MatchTable::Comment("Type") - << MatchTable::NamedValue(CImmLLT->getCxxEnumValue()) + << MatchTable::Comment("Type") << *CImmLLT << MatchTable::Comment("Imm") << MatchTable::IntValue(Imm) << MatchTable::LineBreak; } else { @@ -2093,6 +2165,7 @@ class MatchAction { AK_DebugComment, AK_CustomCXX, AK_BuildMI, + AK_BuildConstantMI, AK_EraseInst, AK_ReplaceReg, AK_ConstraintOpsToDef, @@ -2187,6 +2260,24 @@ class BuildMIAction : public MatchAction { void emitActionOpcodes(MatchTable &Table, RuleMatcher &Rule) const override; }; +/// Generates code to create a constant that defines a TempReg. +/// The instruction created is usually a G_CONSTANT but it could also be a +/// G_BUILD_VECTOR for vector types. +class BuildConstantAction : public MatchAction { + unsigned TempRegID; + int64_t Val; + +public: + BuildConstantAction(unsigned TempRegID, int64_t Val) + : MatchAction(AK_BuildConstantMI), TempRegID(TempRegID), Val(Val) {} + + static bool classof(const MatchAction *A) { + return A->getKind() == AK_BuildConstantMI; + } + + void emitActionOpcodes(MatchTable &Table, RuleMatcher &Rule) const override; +}; + class EraseInstAction : public MatchAction { unsigned InsnID; @@ -2271,13 +2362,14 @@ class ConstrainOperandToRegClassAction : public MatchAction { /// instructions together. class MakeTempRegisterAction : public MatchAction { private: - LLTCodeGen Ty; + LLTCodeGenOrTempType Ty; unsigned TempRegID; public: - MakeTempRegisterAction(const LLTCodeGen &Ty, unsigned TempRegID) + MakeTempRegisterAction(const LLTCodeGenOrTempType &Ty, unsigned TempRegID) : MatchAction(AK_MakeTempReg), Ty(Ty), TempRegID(TempRegID) { - KnownTypes.insert(Ty); + if (Ty.isLLTCodeGen()) + KnownTypes.insert(Ty.getLLTCodeGen()); } static bool classof(const MatchAction *A) { diff --git a/llvm/utils/TableGen/GlobalISelMatchTableExecutorEmitter.cpp b/llvm/utils/TableGen/GlobalISelMatchTableExecutorEmitter.cpp index c6cd3240a94e7..b6f9dbeb336ee 100644 --- a/llvm/utils/TableGen/GlobalISelMatchTableExecutorEmitter.cpp +++ b/llvm/utils/TableGen/GlobalISelMatchTableExecutorEmitter.cpp @@ -232,7 +232,7 @@ void GlobalISelMatchTableExecutorEmitter::emitTemporariesDecl( "const override;\n" << " bool testSimplePredicate(unsigned PredicateID) const override;\n" << " void runCustomAction(unsigned FnID, const MatcherState &State, " - "NewMIVector &OutMIs) " + "ArrayRef OutMIs) " "const override;\n"; emitAdditionalTemporariesDecl(OS, " "); OS << "#endif // ifdef " << IfDefName << "\n\n";