From 6ef829941b38f7e8a28c4cba1ff25cd0ae9f7d3d Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Wed, 27 Mar 2024 19:11:17 +0000 Subject: [PATCH 1/5] Recommit "[VPlan] Replace disjoint or with add instead of dropping disjoint. (#83821)" Recommit with a fix for the use-after-free causing the revert. This reverts the revert commit f872043e055f4163c3c4b1b86ca0354490174987. Original commit message: Dropping disjoint from an OR may yield incorrect results, as some analysis may have converted it to an Add implicitly (e.g. SCEV used for dependence analysis). Instead, replace it with an equivalent Add. This is possible as all users of the disjoint OR only access lanes where the operands are disjoint or poison otherwise. Note that replacing all disjoint ORs with ADDs instead of dropping the flags is not strictly necessary. It is only needed for disjoint ORs that SCEV treated as ADDs, but those are not tracked. There are other places that may drop poison-generating flags; those likely need similar treatment. Fixes https://github.com/llvm/llvm-project/issues/81872 PR: https://github.com/llvm/llvm-project/pull/83821 --- .../Vectorize/LoopVectorizationPlanner.h | 3 +++ llvm/lib/Transforms/Vectorize/VPlan.h | 6 ++++++ .../Transforms/Vectorize/VPlanPatternMatch.h | 5 +++++ .../Transforms/Vectorize/VPlanTransforms.cpp | 19 ++++++++++++++++++- .../Transforms/LoopVectorize/X86/pr81872.ll | 2 +- 5 files changed, 33 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h b/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h index e86705e8988904..5d03b66b0ce335 100644 --- a/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h +++ b/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h @@ -68,6 +68,9 @@ class VPBuilder { public: VPBuilder() = default; VPBuilder(VPBasicBlock *InsertBB) { setInsertPoint(InsertBB); } + VPBuilder(VPRecipeBase *InsertPt) { + setInsertPoint(InsertPt->getParent(), InsertPt->getIterator()); + } /// Clear the insertion point: created instructions will not be inserted into /// a block. diff --git a/llvm/lib/Transforms/Vectorize/VPlan.h b/llvm/lib/Transforms/Vectorize/VPlan.h index f70ccf8270b214..2f56799a7b5186 100644 --- a/llvm/lib/Transforms/Vectorize/VPlan.h +++ b/llvm/lib/Transforms/Vectorize/VPlan.h @@ -1127,6 +1127,12 @@ class VPRecipeWithIRFlags : public VPSingleDefRecipe { return WrapFlags.HasNSW; } + bool isDisjoint() const { + assert(OpType == OperationType::DisjointOp && + "recipe cannot have a disjoing flag"); + return DisjointFlags.IsDisjoint; + } + #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) void printFlags(raw_ostream &O) const; #endif diff --git a/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h b/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h index aa253590694514..a03a408686ef13 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h +++ b/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h @@ -261,6 +261,11 @@ m_Mul(const Op0_t &Op0, const Op1_t &Op1) { return m_Binary(Op0, Op1); } +template +inline AllBinaryRecipe_match +m_Or(const Op0_t &Op0, const Op1_t &Op1) { + return m_Binary(Op0, Op1); +} } // namespace VPlanPatternMatch } // namespace llvm diff --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp index e6ab27a918bcec..006f4349d6fb91 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp @@ -1255,7 +1255,24 @@ void VPlanTransforms::dropPoisonGeneratingRecipes( // load/store. If the underlying instruction has poison-generating flags, // drop them directly. if (auto *RecWithFlags = dyn_cast(CurRec)) { - RecWithFlags->dropPoisonGeneratingFlags(); + VPValue *A, *B; + using namespace llvm::VPlanPatternMatch; + // Dropping disjoint from an OR may yield incorrect results, as some + // analysis may have converted it to an Add implicitly (e.g. SCEV used + // for dependence analysis). Instead, replace it with an equivalent Add. + // This is possible as all users of the disjoint OR only access lanes + // where the operands are disjoint or poison otherwise. + if (match(RecWithFlags, m_Or(m_VPValue(A), m_VPValue(B))) && + RecWithFlags->isDisjoint()) { + VPBuilder Builder(RecWithFlags); + VPInstruction *New = Builder.createOverflowingOp( + Instruction::Add, {A, B}, {false, false}, + RecWithFlags->getDebugLoc()); + RecWithFlags->replaceAllUsesWith(New); + RecWithFlags->eraseFromParent(); + CurRec = New; + } else + RecWithFlags->dropPoisonGeneratingFlags(); } else { Instruction *Instr = dyn_cast_or_null( CurRec->getVPSingleValue()->getUnderlyingValue()); diff --git a/llvm/test/Transforms/LoopVectorize/X86/pr81872.ll b/llvm/test/Transforms/LoopVectorize/X86/pr81872.ll index 14acb6f57aa0c9..3f38abc75a5837 100644 --- a/llvm/test/Transforms/LoopVectorize/X86/pr81872.ll +++ b/llvm/test/Transforms/LoopVectorize/X86/pr81872.ll @@ -29,7 +29,7 @@ define void @test(ptr noundef align 8 dereferenceable_or_null(16) %arr) #0 { ; CHECK-NEXT: [[TMP2:%.*]] = and <4 x i64> [[VEC_IND]], ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq <4 x i64> [[TMP2]], zeroinitializer ; CHECK-NEXT: [[TMP4:%.*]] = select <4 x i1> [[TMP1]], <4 x i1> [[TMP3]], <4 x i1> zeroinitializer -; CHECK-NEXT: [[TMP5:%.*]] = or i64 [[TMP0]], 1 +; CHECK-NEXT: [[TMP5:%.*]] = add i64 [[TMP0]], 1 ; CHECK-NEXT: [[TMP6:%.*]] = getelementptr i64, ptr [[ARR]], i64 [[TMP5]] ; CHECK-NEXT: [[TMP7:%.*]] = getelementptr i64, ptr [[TMP6]], i32 0 ; CHECK-NEXT: [[TMP8:%.*]] = getelementptr i64, ptr [[TMP7]], i32 -3 From c2bdbedf1c2326cb3b38cedf0ee46413d86e2e2c Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Wed, 27 Mar 2024 15:13:05 -0400 Subject: [PATCH 2/5] [libc++][NFC] Remove whitespace that doesn't belong --- libcxx/utils/libcxx/test/params.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcxx/utils/libcxx/test/params.py b/libcxx/utils/libcxx/test/params.py index 695e01115aa4ba..5e42562ed5db52 100644 --- a/libcxx/utils/libcxx/test/params.py +++ b/libcxx/utils/libcxx/test/params.py @@ -407,6 +407,6 @@ def getSuitableClangTidy(cfg): AddFeature('has-clang-tidy'), AddSubstitution('%{clang-tidy}', exe), ] - ), + ), ] # fmt: on From aeb8628c218f8224e08dddcdd3199a445d8607a8 Mon Sep 17 00:00:00 2001 From: Neumann Hon Date: Wed, 27 Mar 2024 15:15:32 -0400 Subject: [PATCH 3/5] Revert "[SystemZ][z/OS] TXT records in the GOFF reader (#74526)" This reverts commit 009f88fc0e3a036be97ef7b222b90af342bae0b7. Reverting PR due to test failure. --- llvm/include/llvm/Object/GOFF.h | 20 ---- llvm/include/llvm/Object/GOFFObjectFile.h | 56 +++-------- llvm/lib/Object/GOFFObjectFile.cpp | 19 ---- llvm/unittests/Object/GOFFObjectFileTest.cpp | 97 -------------------- 4 files changed, 14 insertions(+), 178 deletions(-) diff --git a/llvm/include/llvm/Object/GOFF.h b/llvm/include/llvm/Object/GOFF.h index 9fb8876e893d57..91762457ae0563 100644 --- a/llvm/include/llvm/Object/GOFF.h +++ b/llvm/include/llvm/Object/GOFF.h @@ -73,26 +73,6 @@ class Record { } }; -class TXTRecord : public Record { -public: - /// \brief Maximum length of data; any more must go in continuation. - static const uint8_t TXTMaxDataLength = 56; - - static Error getData(const uint8_t *Record, SmallString<256> &CompleteData); - - static void getElementEsdId(const uint8_t *Record, uint32_t &EsdId) { - get(Record, 4, EsdId); - } - - static void getOffset(const uint8_t *Record, uint32_t &Offset) { - get(Record, 12, Offset); - } - - static void getDataLength(const uint8_t *Record, uint16_t &Length) { - get(Record, 22, Length); - } -}; - class HDRRecord : public Record { public: static Error getData(const uint8_t *Record, SmallString<256> &CompleteData); diff --git a/llvm/include/llvm/Object/GOFFObjectFile.h b/llvm/include/llvm/Object/GOFFObjectFile.h index 6871641e97ec8d..7e1ceb95f66723 100644 --- a/llvm/include/llvm/Object/GOFFObjectFile.h +++ b/llvm/include/llvm/Object/GOFFObjectFile.h @@ -29,10 +29,7 @@ namespace llvm { namespace object { class GOFFObjectFile : public ObjectFile { - friend class GOFFSymbolRef; - IndexedMap EsdPtrs; // Indexed by EsdId. - SmallVector TextPtrs; mutable DenseMap>> EsdNamesCache; @@ -41,7 +38,7 @@ class GOFFObjectFile : public ObjectFile { // (EDID, 0) code, r/o data section // (EDID,PRID) r/w data section SmallVector SectionList; - mutable DenseMap> SectionDataCache; + mutable DenseMap SectionDataCache; public: Expected getSymbolName(SymbolRef Symbol) const; @@ -69,10 +66,6 @@ class GOFFObjectFile : public ObjectFile { return true; } - bool isSectionNoLoad(DataRefImpl Sec) const; - bool isSectionReadOnlyData(DataRefImpl Sec) const; - bool isSectionZeroInit(DataRefImpl Sec) const; - private: // SymbolRef. Expected getSymbolName(DataRefImpl Symb) const override; @@ -82,24 +75,27 @@ class GOFFObjectFile : public ObjectFile { Expected getSymbolFlags(DataRefImpl Symb) const override; Expected getSymbolType(DataRefImpl Symb) const override; Expected getSymbolSection(DataRefImpl Symb) const override; - uint64_t getSymbolSize(DataRefImpl Symb) const; const uint8_t *getSymbolEsdRecord(DataRefImpl Symb) const; bool isSymbolUnresolved(DataRefImpl Symb) const; bool isSymbolIndirect(DataRefImpl Symb) const; // SectionRef. - void moveSectionNext(DataRefImpl &Sec) const override; - virtual Expected getSectionName(DataRefImpl Sec) const override; - uint64_t getSectionAddress(DataRefImpl Sec) const override; - uint64_t getSectionSize(DataRefImpl Sec) const override; + void moveSectionNext(DataRefImpl &Sec) const override {} + virtual Expected getSectionName(DataRefImpl Sec) const override { + return StringRef(); + } + uint64_t getSectionAddress(DataRefImpl Sec) const override { return 0; } + uint64_t getSectionSize(DataRefImpl Sec) const override { return 0; } virtual Expected> - getSectionContents(DataRefImpl Sec) const override; - uint64_t getSectionIndex(DataRefImpl Sec) const override { return Sec.d.a; } - uint64_t getSectionAlignment(DataRefImpl Sec) const override; + getSectionContents(DataRefImpl Sec) const override { + return ArrayRef(); + } + uint64_t getSectionIndex(DataRefImpl Sec) const override { return 0; } + uint64_t getSectionAlignment(DataRefImpl Sec) const override { return 0; } bool isSectionCompressed(DataRefImpl Sec) const override { return false; } - bool isSectionText(DataRefImpl Sec) const override; - bool isSectionData(DataRefImpl Sec) const override; + bool isSectionText(DataRefImpl Sec) const override { return false; } + bool isSectionData(DataRefImpl Sec) const override { return false; } bool isSectionBSS(DataRefImpl Sec) const override { return false; } bool isSectionVirtual(DataRefImpl Sec) const override { return false; } relocation_iterator section_rel_begin(DataRefImpl Sec) const override { @@ -113,7 +109,6 @@ class GOFFObjectFile : public ObjectFile { const uint8_t *getSectionPrEsdRecord(DataRefImpl &Sec) const; const uint8_t *getSectionEdEsdRecord(uint32_t SectionIndex) const; const uint8_t *getSectionPrEsdRecord(uint32_t SectionIndex) const; - uint32_t getSectionDefEsdId(DataRefImpl &Sec) const; // RelocationRef. void moveRelocationNext(DataRefImpl &Rel) const override {} @@ -127,29 +122,6 @@ class GOFFObjectFile : public ObjectFile { SmallVectorImpl &Result) const override {} }; -class GOFFSymbolRef : public SymbolRef { -public: - GOFFSymbolRef(const SymbolRef &B) : SymbolRef(B) { - assert(isa(SymbolRef::getObject())); - } - - const GOFFObjectFile *getObject() const { - return cast(BasicSymbolRef::getObject()); - } - - Expected getSymbolGOFFFlags() const { - return getObject()->getSymbolFlags(getRawDataRefImpl()); - } - - Expected getSymbolGOFFType() const { - return getObject()->getSymbolType(getRawDataRefImpl()); - } - - uint64_t getSize() const { - return getObject()->getSymbolSize(getRawDataRefImpl()); - } -}; - } // namespace object } // namespace llvm diff --git a/llvm/lib/Object/GOFFObjectFile.cpp b/llvm/lib/Object/GOFFObjectFile.cpp index 2845d9362544bb..d8e1ddf2aef864 100644 --- a/llvm/lib/Object/GOFFObjectFile.cpp +++ b/llvm/lib/Object/GOFFObjectFile.cpp @@ -168,11 +168,6 @@ GOFFObjectFile::GOFFObjectFile(MemoryBufferRef Object, Error &Err) LLVM_DEBUG(dbgs() << " -- ESD " << EsdId << "\n"); break; } - case GOFF::RT_TXT: - // Save TXT records. - TextPtrs.emplace_back(I); - LLVM_DEBUG(dbgs() << " -- TXT\n"); - break; case GOFF::RT_END: LLVM_DEBUG(dbgs() << " -- END (GOFF record type) unhandled\n"); break; @@ -369,13 +364,6 @@ GOFFObjectFile::getSymbolSection(DataRefImpl Symb) const { std::to_string(SymEdId)); } -uint64_t GOFFObjectFile::getSymbolSize(DataRefImpl Symb) const { - const uint8_t *Record = getSymbolEsdRecord(Symb); - uint32_t Length; - ESDRecord::getLength(Record, Length); - return Length; -} - const uint8_t *GOFFObjectFile::getSectionEdEsdRecord(DataRefImpl &Sec) const { SectionEntryImpl EsdIds = SectionList[Sec.d.a]; const uint8_t *EsdRecord = EsdPtrs[EsdIds.d.a]; @@ -636,13 +624,6 @@ Error ESDRecord::getData(const uint8_t *Record, return getContinuousData(Record, DataSize, 72, CompleteData); } -Error TXTRecord::getData(const uint8_t *Record, - SmallString<256> &CompleteData) { - uint16_t Length; - getDataLength(Record, Length); - return getContinuousData(Record, Length, 24, CompleteData); -} - Error ENDRecord::getData(const uint8_t *Record, SmallString<256> &CompleteData) { uint16_t Length = getNameLength(Record); diff --git a/llvm/unittests/Object/GOFFObjectFileTest.cpp b/llvm/unittests/Object/GOFFObjectFileTest.cpp index 69f60d016a8081..734dac6b8507a7 100644 --- a/llvm/unittests/Object/GOFFObjectFileTest.cpp +++ b/llvm/unittests/Object/GOFFObjectFileTest.cpp @@ -502,100 +502,3 @@ TEST(GOFFObjectFileTest, InvalidERSymbolType) { FailedWithMessage("ESD record 1 has unknown Executable type 0x03")); } } - -TEST(GOFFObjectFileTest, TXTConstruct) { - char GOFFData[GOFF::RecordLength * 6] = {}; - - // HDR record. - GOFFData[0] = 0x03; - GOFFData[1] = 0xF0; - GOFFData[50] = 0x01; - - // ESD record. - GOFFData[GOFF::RecordLength] = 0x03; - GOFFData[GOFF::RecordLength + 7] = 0x01; // ESDID. - GOFFData[GOFF::RecordLength + 71] = 0x05; // Size of symbol name. - GOFFData[GOFF::RecordLength + 72] = 0xa5; // Symbol name is v. - GOFFData[GOFF::RecordLength + 73] = 0x81; // Symbol name is a. - GOFFData[GOFF::RecordLength + 74] = 0x99; // Symbol name is r. - GOFFData[GOFF::RecordLength + 75] = 0x7b; // Symbol name is #. - GOFFData[GOFF::RecordLength + 76] = 0x83; // Symbol name is c. - - // ESD record. - GOFFData[GOFF::RecordLength * 2] = 0x03; - GOFFData[GOFF::RecordLength * 2 + 3] = 0x01; - GOFFData[GOFF::RecordLength * 2 + 7] = 0x02; // ESDID. - GOFFData[GOFF::RecordLength * 2 + 11] = 0x01; // Parent ESDID. - GOFFData[GOFF::RecordLength * 2 + 27] = 0x08; // Length. - GOFFData[GOFF::RecordLength * 2 + 40] = 0x01; // Name Space ID. - GOFFData[GOFF::RecordLength * 2 + 41] = 0x80; - GOFFData[GOFF::RecordLength * 2 + 60] = 0x04; // Size of symbol name. - GOFFData[GOFF::RecordLength * 2 + 61] = 0x04; // Size of symbol name. - GOFFData[GOFF::RecordLength * 2 + 63] = 0x0a; // Size of symbol name. - GOFFData[GOFF::RecordLength * 2 + 66] = 0x03; // Size of symbol name. - GOFFData[GOFF::RecordLength * 2 + 71] = 0x08; // Size of symbol name. - GOFFData[GOFF::RecordLength * 2 + 72] = 0xc3; // Symbol name is c. - GOFFData[GOFF::RecordLength * 2 + 73] = 0x6d; // Symbol name is _. - GOFFData[GOFF::RecordLength * 2 + 74] = 0xc3; // Symbol name is c. - GOFFData[GOFF::RecordLength * 2 + 75] = 0xd6; // Symbol name is o. - GOFFData[GOFF::RecordLength * 2 + 76] = 0xc4; // Symbol name is D. - GOFFData[GOFF::RecordLength * 2 + 77] = 0xc5; // Symbol name is E. - GOFFData[GOFF::RecordLength * 2 + 78] = 0xf6; // Symbol name is 6. - GOFFData[GOFF::RecordLength * 2 + 79] = 0xf4; // Symbol name is 4. - - // ESD record. - GOFFData[GOFF::RecordLength * 3] = 0x03; - GOFFData[GOFF::RecordLength * 3 + 3] = 0x02; - GOFFData[GOFF::RecordLength * 3 + 7] = 0x03; // ESDID. - GOFFData[GOFF::RecordLength * 3 + 11] = 0x02; // Parent ESDID. - GOFFData[GOFF::RecordLength * 3 + 71] = 0x05; // Size of symbol name. - GOFFData[GOFF::RecordLength * 3 + 72] = 0xa5; // Symbol name is v. - GOFFData[GOFF::RecordLength * 3 + 73] = 0x81; // Symbol name is a. - GOFFData[GOFF::RecordLength * 3 + 74] = 0x99; // Symbol name is r. - GOFFData[GOFF::RecordLength * 3 + 75] = 0x7b; // Symbol name is #. - GOFFData[GOFF::RecordLength * 3 + 76] = 0x83; // Symbol name is c. - - // TXT record. - GOFFData[GOFF::RecordLength * 4] = 0x03; - GOFFData[GOFF::RecordLength * 4 + 1] = 0x10; - GOFFData[GOFF::RecordLength * 4 + 7] = 0x02; - GOFFData[GOFF::RecordLength * 4 + 23] = 0x08; // Data Length. - GOFFData[GOFF::RecordLength * 4 + 24] = 0x12; - GOFFData[GOFF::RecordLength * 4 + 25] = 0x34; - GOFFData[GOFF::RecordLength * 4 + 26] = 0x56; - GOFFData[GOFF::RecordLength * 4 + 27] = 0x78; - GOFFData[GOFF::RecordLength * 4 + 28] = 0x9a; - GOFFData[GOFF::RecordLength * 4 + 29] = 0xbc; - GOFFData[GOFF::RecordLength * 4 + 30] = 0xde; - GOFFData[GOFF::RecordLength * 4 + 31] = 0xf0; - - // END record. - GOFFData[GOFF::RecordLength * 5] = 0x03; - GOFFData[GOFF::RecordLength * 5 + 1] = 0x40; - GOFFData[GOFF::RecordLength * 5 + 11] = 0x06; - - StringRef Data(GOFFData, GOFF::RecordLength * 6); - - Expected> GOFFObjOrErr = - object::ObjectFile::createGOFFObjectFile( - MemoryBufferRef(Data, "dummyGOFF")); - - ASSERT_THAT_EXPECTED(GOFFObjOrErr, Succeeded()); - - GOFFObjectFile *GOFFObj = dyn_cast((*GOFFObjOrErr).get()); - auto Symbols = GOFFObj->symbols(); - ASSERT_EQ(std::distance(Symbols.begin(), Symbols.end()), 1); - SymbolRef Symbol = *Symbols.begin(); - Expected SymbolNameOrErr = GOFFObj->getSymbolName(Symbol); - ASSERT_THAT_EXPECTED(SymbolNameOrErr, Succeeded()); - StringRef SymbolName = SymbolNameOrErr.get(); - EXPECT_EQ(SymbolName, "var#c"); - - auto Sections = GOFFObj->sections(); - ASSERT_EQ(std::distance(Sections.begin(), Sections.end()), 1); - SectionRef Section = *Sections.begin(); - Expected SectionContent = Section.getContents(); - ASSERT_THAT_EXPECTED(SectionContent, Succeeded()); - StringRef Contents = SectionContent.get(); - EXPECT_EQ(Contents, "\x12\x34\x56\x78\x9a\xbc\xde\xf0"); -} From baf66ec061aa4da85d6bdfd1f9cd1030b9607fbb Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Wed, 27 Mar 2024 12:19:28 -0700 Subject: [PATCH 4/5] [Target][RISCV] Add HwMode support to subregister index size/offset. (#86368) This is needed to provide proper size and offset for the GPRPair subreg indices on RISC-V. The size of a GPR already uses HwMode. Previously we said the subreg indices have unknown size and offset, but this stops DwarfExpression::addMachineReg from being able to find the registers that make up the pair. I believe this fixes https://github.com/llvm/llvm-project/issues/85864 but need to verify. --- llvm/include/llvm/Target/Target.td | 17 ++++ llvm/lib/CodeGen/TargetRegisterInfo.cpp | 4 +- llvm/lib/Target/RISCV/RISCVRegisterInfo.td | 11 ++- llvm/test/TableGen/ConcatenatedSubregs.td | 9 ++- llvm/test/TableGen/HwModeSubRegs.td | 75 ++++++++++++++++++ .../TableGen/Common/CodeGenRegisters.cpp | 79 +++++++++++++------ llvm/utils/TableGen/Common/CodeGenRegisters.h | 43 +++++++--- llvm/utils/TableGen/Common/InfoByHwMode.cpp | 14 ++++ llvm/utils/TableGen/Common/InfoByHwMode.h | 21 ++++- llvm/utils/TableGen/RegisterInfoEmitter.cpp | 19 +++-- 10 files changed, 242 insertions(+), 50 deletions(-) create mode 100644 llvm/test/TableGen/HwModeSubRegs.td diff --git a/llvm/include/llvm/Target/Target.td b/llvm/include/llvm/Target/Target.td index cb1c0ed2513d45..1f7dc6922f13e4 100644 --- a/llvm/include/llvm/Target/Target.td +++ b/llvm/include/llvm/Target/Target.td @@ -83,10 +83,27 @@ class RegInfoByHwMode Ms = [], list Ts = []> list Objects = Ts; } +class SubRegRange { + int Size = size; // Sub register size in bits. + int Offset = offset; // Offset of the first bit of the sub-reg index. +} + +class SubRegRangeByHwMode Ms = [], list Ts = []> + : HwModeSelect { + // The length of this list must be the same as the length of Ms. + list Objects = Ts; +} + // SubRegIndex - Use instances of SubRegIndex to identify subregisters. class SubRegIndex { string Namespace = ""; + // The size/offset information, parameterized by a HW mode. + // If the HwModes provided for SubRegRanges does not include the DefaultMode, + // the/ Size and Offset fields below will be used for the default. Otherwise, + // the Size and Offset fields are ignored. + SubRegRangeByHwMode SubRegRanges; + // Size - Size (in bits) of the sub-registers represented by this index. int Size = size; diff --git a/llvm/lib/CodeGen/TargetRegisterInfo.cpp b/llvm/lib/CodeGen/TargetRegisterInfo.cpp index 4120c74c23b193..4e06393f4cc1d3 100644 --- a/llvm/lib/CodeGen/TargetRegisterInfo.cpp +++ b/llvm/lib/CodeGen/TargetRegisterInfo.cpp @@ -595,13 +595,13 @@ bool TargetRegisterInfo::getCoveringSubRegIndexes( unsigned TargetRegisterInfo::getSubRegIdxSize(unsigned Idx) const { assert(Idx && Idx < getNumSubRegIndices() && "This is not a subregister index"); - return SubRegIdxRanges[Idx].Size; + return SubRegIdxRanges[HwMode * getNumSubRegIndices() + Idx].Size; } unsigned TargetRegisterInfo::getSubRegIdxOffset(unsigned Idx) const { assert(Idx && Idx < getNumSubRegIndices() && "This is not a subregister index"); - return SubRegIdxRanges[Idx].Offset; + return SubRegIdxRanges[HwMode * getNumSubRegIndices() + Idx].Offset; } Register diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td index 9da1f73681c68c..90c4a7193ee337 100644 --- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td +++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td @@ -64,9 +64,14 @@ def sub_vrm1_6 : ComposedSubRegIndex; def sub_vrm1_7 : ComposedSubRegIndex; // GPR sizes change with HwMode. -// FIXME: Support HwMode in SubRegIndex? -def sub_gpr_even : SubRegIndex<-1>; -def sub_gpr_odd : SubRegIndex<-1, -1>; +def sub_gpr_even : SubRegIndex<32> { + let SubRegRanges = SubRegRangeByHwMode<[RV32, RV64], + [SubRegRange<32>, SubRegRange<64>]>; +} +def sub_gpr_odd : SubRegIndex<32, 32> { + let SubRegRanges = SubRegRangeByHwMode<[RV32, RV64], + [SubRegRange<32, 32>, SubRegRange<64, 64>]>; +} } // Namespace = "RISCV" // Integer registers diff --git a/llvm/test/TableGen/ConcatenatedSubregs.td b/llvm/test/TableGen/ConcatenatedSubregs.td index 5b354c94dca52c..ea4e7f01a2e2da 100644 --- a/llvm/test/TableGen/ConcatenatedSubregs.td +++ b/llvm/test/TableGen/ConcatenatedSubregs.td @@ -90,16 +90,19 @@ def TestTarget : Target; // CHECK-LABEL: RegisterClass DRegs: // CHECK-LABEL: SubRegIndex ssub1: -// CHECK: Offset, Size: 16, 16 +// CHECK: Offset: { Default:16 } +// CHECK: Size: { Default:16 } // CHECK-LABEL: SubRegIndex sub0: // CHECK-LABEL: SubRegIndex sub1: // CHECK-LABEL: SubRegIndex sub2: // Check inferred indexes: // CHECK-LABEL: SubRegIndex ssub1_ssub2: -// CHECK: Offset, Size: 16, 65535 +// CHECK: Offset: { Default:16 } +// CHECK: Size: { Default:65535 } // CHECK-LABEL: SubRegIndex ssub3_ssub4: // CHECK-LABEL: SubRegIndex ssub0_ssub1_ssub2_ssub3: -// CHECK: Offset, Size: 65535, 65535 +// CHECK: Offset: { Default:65535 } +// CHECK: Size: { Default:65535 } // CHECK-LABEL: SubRegIndex ssub1_ssub2_ssub3_ssub4: // Check that all subregs are generated on some examples diff --git a/llvm/test/TableGen/HwModeSubRegs.td b/llvm/test/TableGen/HwModeSubRegs.td new file mode 100644 index 00000000000000..2bf7a917979d99 --- /dev/null +++ b/llvm/test/TableGen/HwModeSubRegs.td @@ -0,0 +1,75 @@ +// RUN: llvm-tblgen -gen-register-info -register-info-debug -I %p/../../include %s -o /dev/null 2>&1 | FileCheck %s +include "llvm/Target/Target.td" + +def HasFeat : Predicate<"Subtarget->hasFeat()">; + +def TestMode : HwMode<"+feat1", [HasFeat]>; + +class MyReg + : Register { + let Namespace = "Test"; +} +class MyClass types, dag registers> + : RegisterClass<"Test", types, size, registers> { + let Size = size; +} + +def X0 : MyReg<"x0">; +def X1 : MyReg<"x1">; +def X2 : MyReg<"x2">; +def X3 : MyReg<"x3">; +def X4 : MyReg<"x4">; +def X5 : MyReg<"x5">; +def X6 : MyReg<"x6">; +def X7 : MyReg<"x7">; +def X8 : MyReg<"x8">; +def X9 : MyReg<"x9">; +def X10 : MyReg<"x10">; +def X11 : MyReg<"x11">; +def X12 : MyReg<"x12">; +def X13 : MyReg<"x13">; +def X14 : MyReg<"x14">; +def X15 : MyReg<"x15">; + +def ModeVT : ValueTypeByHwMode<[DefaultMode, TestMode], + [i32, i64]>; +let RegInfos = RegInfoByHwMode<[DefaultMode, TestMode], + [RegInfo<32,32,32>, RegInfo<64,64,64>]> in +def XRegs : MyClass<32, [ModeVT], (sequence "X%u", 0, 15)>; + +def sub_even : SubRegIndex<32> { + let SubRegRanges = SubRegRangeByHwMode<[DefaultMode, TestMode], + [SubRegRange<32>, SubRegRange<64>]>; +} +def sub_odd : SubRegIndex<32, 32> { + let SubRegRanges = SubRegRangeByHwMode<[DefaultMode, TestMode], + [SubRegRange<32, 32>, SubRegRange<64, 64>]>; +} + +def XPairs : RegisterTuples<[sub_even, sub_odd], + [(decimate (rotl XRegs, 0), 2), + (decimate (rotl XRegs, 1), 2)]>; + +let RegInfos = RegInfoByHwMode<[DefaultMode, TestMode], + [RegInfo<64,64,32>, RegInfo<128,128,64>]> in +def XPairsClass : MyClass<64, [untyped], (add XPairs)>; + +def TestTarget : Target; + +// CHECK-LABEL: RegisterClass XRegs: +// CHECK: SpillSize: { Default:32 TestMode:64 } +// CHECK: SpillAlignment: { Default:32 TestMode:64 } +// CHECK: Regs: X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 + +// CHECK-LABEL: RegisterClass XPairsClass: +// CHECK: SpillSize: { Default:64 TestMode:128 } +// CHECK: SpillAlignment: { Default:32 TestMode:64 } +// CHECK: CoveredBySubRegs: 1 +// CHECK: Regs: X0_X1 X2_X3 X4_X5 X6_X7 X8_X9 X10_X11 X12_X13 X14_X15 + +// CHECK-LABEL: SubRegIndex sub_even: +// CHECK: Offset: { Default:0 TestMode:0 } +// CHECK: Size: { Default:32 TestMode:64 } +// CHECK-LABEL: SubRegIndex sub_odd: +// CHECK: Offset: { Default:32 TestMode:64 } +// CHECK: Size: { Default:32 TestMode:64 } diff --git a/llvm/utils/TableGen/Common/CodeGenRegisters.cpp b/llvm/utils/TableGen/Common/CodeGenRegisters.cpp index e851d4c16bf7b6..624e8d5d54ba8f 100644 --- a/llvm/utils/TableGen/Common/CodeGenRegisters.cpp +++ b/llvm/utils/TableGen/Common/CodeGenRegisters.cpp @@ -47,19 +47,24 @@ using namespace llvm; // CodeGenSubRegIndex //===----------------------------------------------------------------------===// -CodeGenSubRegIndex::CodeGenSubRegIndex(Record *R, unsigned Enum) +CodeGenSubRegIndex::CodeGenSubRegIndex(Record *R, unsigned Enum, + const CodeGenHwModes &CGH) : TheDef(R), EnumValue(Enum), AllSuperRegsCovered(true), Artificial(true) { Name = std::string(R->getName()); if (R->getValue("Namespace")) Namespace = std::string(R->getValueAsString("Namespace")); - Size = R->getValueAsInt("Size"); - Offset = R->getValueAsInt("Offset"); + + if (const RecordVal *RV = R->getValue("SubRegRanges")) + if (auto *DI = dyn_cast_or_null(RV->getValue())) + Range = SubRegRangeByHwMode(DI->getDef(), CGH); + if (!Range.hasDefault()) + Range.insertSubRegRangeForMode(DefaultMode, SubRegRange(R)); } CodeGenSubRegIndex::CodeGenSubRegIndex(StringRef N, StringRef Nspace, unsigned Enum) : TheDef(nullptr), Name(std::string(N)), Namespace(std::string(Nspace)), - Size(-1), Offset(-1), EnumValue(Enum), AllSuperRegsCovered(true), + Range(SubRegRange(-1, -1)), EnumValue(Enum), AllSuperRegsCovered(true), Artificial(true) {} std::string CodeGenSubRegIndex::getQualifiedName() const { @@ -81,7 +86,7 @@ void CodeGenSubRegIndex::updateComponents(CodeGenRegBank &RegBank) { "ComposedOf must have exactly two entries"); CodeGenSubRegIndex *A = RegBank.getSubRegIdx(Comps[0]); CodeGenSubRegIndex *B = RegBank.getSubRegIdx(Comps[1]); - CodeGenSubRegIndex *X = A->addComposite(B, this); + CodeGenSubRegIndex *X = A->addComposite(B, this, RegBank.getHwModes()); if (X) PrintFatalError(TheDef->getLoc(), "Ambiguous ComposedOf entries"); } @@ -518,7 +523,8 @@ void CodeGenRegister::computeSecondarySubRegs(CodeGenRegBank &RegBank) { // Each part of Cand is a sub-register of this. Make the full Cand also // a sub-register with a concatenated sub-register index. - CodeGenSubRegIndex *Concat = RegBank.getConcatSubRegIndex(Parts); + CodeGenSubRegIndex *Concat = + RegBank.getConcatSubRegIndex(Parts, RegBank.getHwModes()); std::pair NewSubReg = std::pair(Concat, Cand); @@ -542,7 +548,7 @@ void CodeGenRegister::computeSecondarySubRegs(CodeGenRegBank &RegBank) { PrintFatalError(TheDef->getLoc(), "No SubRegIndex for " + SubReg.second->getName() + " in " + getName()); - NewIdx->addComposite(SubReg.first, SubIdx); + NewIdx->addComposite(SubReg.first, SubIdx, RegBank.getHwModes()); } } } @@ -1315,7 +1321,7 @@ CodeGenSubRegIndex *CodeGenRegBank::getSubRegIdx(Record *Def) { CodeGenSubRegIndex *&Idx = Def2SubRegIdx[Def]; if (Idx) return Idx; - SubRegIndices.emplace_back(Def, SubRegIndices.size() + 1); + SubRegIndices.emplace_back(Def, SubRegIndices.size() + 1, getHwModes()); Idx = &SubRegIndices.back(); return Idx; } @@ -1379,12 +1385,13 @@ CodeGenRegBank::getCompositeSubRegIndex(CodeGenSubRegIndex *A, // None exists, synthesize one. std::string Name = A->getName() + "_then_" + B->getName(); Comp = createSubRegIndex(Name, A->getNamespace()); - A->addComposite(B, Comp); + A->addComposite(B, Comp, getHwModes()); return Comp; } CodeGenSubRegIndex *CodeGenRegBank::getConcatSubRegIndex( - const SmallVector &Parts) { + const SmallVector &Parts, + const CodeGenHwModes &CGH) { assert(Parts.size() > 1 && "Need two parts to concatenate"); #ifndef NDEBUG for (CodeGenSubRegIndex *Idx : Parts) { @@ -1399,28 +1406,47 @@ CodeGenSubRegIndex *CodeGenRegBank::getConcatSubRegIndex( // None exists, synthesize one. std::string Name = Parts.front()->getName(); - // Determine whether all parts are contiguous. - bool IsContinuous = true; - unsigned Size = Parts.front()->Size; - unsigned LastOffset = Parts.front()->Offset; - unsigned LastSize = Parts.front()->Size; const unsigned UnknownSize = (uint16_t)-1; + for (unsigned i = 1, e = Parts.size(); i != e; ++i) { Name += '_'; Name += Parts[i]->getName(); - if (Size == UnknownSize || Parts[i]->Size == UnknownSize) - Size = UnknownSize; - else - Size += Parts[i]->Size; - if (LastSize == UnknownSize || Parts[i]->Offset != (LastOffset + LastSize)) - IsContinuous = false; - LastOffset = Parts[i]->Offset; - LastSize = Parts[i]->Size; } + Idx = createSubRegIndex(Name, Parts.front()->getNamespace()); - Idx->Size = Size; - Idx->Offset = IsContinuous ? Parts.front()->Offset : -1; Idx->ConcatenationOf.assign(Parts.begin(), Parts.end()); + + unsigned NumModes = CGH.getNumModeIds(); + for (unsigned M = 0; M < NumModes; ++M) { + const CodeGenSubRegIndex *Part = Parts.front(); + + // Determine whether all parts are contiguous. + bool IsContinuous = true; + const SubRegRange &FirstPartRange = Part->Range.get(M); + unsigned Size = FirstPartRange.Size; + unsigned LastOffset = FirstPartRange.Offset; + unsigned LastSize = FirstPartRange.Size; + + for (unsigned i = 1, e = Parts.size(); i != e; ++i) { + Part = Parts[i]; + Name += '_'; + Name += Part->getName(); + + const SubRegRange &PartRange = Part->Range.get(M); + if (Size == UnknownSize || PartRange.Size == UnknownSize) + Size = UnknownSize; + else + Size += PartRange.Size; + if (LastSize == UnknownSize || + PartRange.Offset != (LastOffset + LastSize)) + IsContinuous = false; + LastOffset = PartRange.Offset; + LastSize = PartRange.Size; + } + unsigned Offset = IsContinuous ? FirstPartRange.Offset : -1; + Idx->Range.get(M) = SubRegRange(Size, Offset); + } + return Idx; } @@ -1504,7 +1530,8 @@ void CodeGenRegBank::computeComposites() { assert(Idx3 && "Sub-register doesn't have an index"); // Conflicting composition? Emit a warning but allow it. - if (CodeGenSubRegIndex *Prev = Idx1->addComposite(Idx2, Idx3)) { + if (CodeGenSubRegIndex *Prev = + Idx1->addComposite(Idx2, Idx3, getHwModes())) { // If the composition was not user-defined, always emit a warning. if (!UserDefined.count({Idx1, Idx2}) || agree(compose(Idx1, Idx2), SubRegAction.at(Idx3))) diff --git a/llvm/utils/TableGen/Common/CodeGenRegisters.h b/llvm/utils/TableGen/Common/CodeGenRegisters.h index c34f376ea99db3..9058baea2b23e9 100644 --- a/llvm/utils/TableGen/Common/CodeGenRegisters.h +++ b/llvm/utils/TableGen/Common/CodeGenRegisters.h @@ -68,8 +68,7 @@ class CodeGenSubRegIndex { std::string Namespace; public: - uint16_t Size; - uint16_t Offset; + SubRegRangeByHwMode Range; const unsigned EnumValue; mutable LaneBitmask LaneMask; mutable SmallVector CompositionLaneMaskTransform; @@ -86,7 +85,7 @@ class CodeGenSubRegIndex { // indexes are not used to create new register classes. bool Artificial; - CodeGenSubRegIndex(Record *R, unsigned Enum); + CodeGenSubRegIndex(Record *R, unsigned Enum, const CodeGenHwModes &CGH); CodeGenSubRegIndex(StringRef N, StringRef Nspace, unsigned Enum); CodeGenSubRegIndex(CodeGenSubRegIndex &) = delete; @@ -108,19 +107,42 @@ class CodeGenSubRegIndex { // Add a composite subreg index: this+A = B. // Return a conflicting composite, or NULL - CodeGenSubRegIndex *addComposite(CodeGenSubRegIndex *A, - CodeGenSubRegIndex *B) { + CodeGenSubRegIndex *addComposite(CodeGenSubRegIndex *A, CodeGenSubRegIndex *B, + const CodeGenHwModes &CGH) { assert(A && B); std::pair Ins = Composed.insert(std::pair(A, B)); + // Synthetic subreg indices that aren't contiguous (for instance ARM // register tuples) don't have a bit range, so it's OK to let // B->Offset == -1. For the other cases, accumulate the offset and set // the size here. Only do so if there is no offset yet though. - if ((Offset != (uint16_t)-1 && A->Offset != (uint16_t)-1) && - (B->Offset == (uint16_t)-1)) { - B->Offset = Offset + A->Offset; - B->Size = A->Size; + unsigned NumModes = CGH.getNumModeIds(); + // Skip default mode. + for (unsigned M = 0; M < NumModes; ++M) { + // Handle DefaultMode last. + if (M == DefaultMode) + continue; + SubRegRange &Range = this->Range.get(M); + SubRegRange &ARange = A->Range.get(M); + SubRegRange &BRange = B->Range.get(M); + + if (Range.Offset != (uint16_t)-1 && ARange.Offset != (uint16_t)-1 && + BRange.Offset == (uint16_t)-1) { + BRange.Offset = Range.Offset + ARange.Offset; + BRange.Size = ARange.Size; + } + } + + // Now handle default. + SubRegRange &Range = this->Range.get(DefaultMode); + SubRegRange &ARange = A->Range.get(DefaultMode); + SubRegRange &BRange = B->Range.get(DefaultMode); + if (Range.Offset != (uint16_t)-1 && ARange.Offset != (uint16_t)-1 && + BRange.Offset == (uint16_t)-1) { + BRange.Offset = Range.Offset + ARange.Offset; + BRange.Size = ARange.Size; } + return (Ins.second || Ins.first->second == B) ? nullptr : Ins.first->second; } @@ -681,7 +703,8 @@ class CodeGenRegBank { // Find or create a sub-register index representing the concatenation of // non-overlapping sibling indices. CodeGenSubRegIndex * - getConcatSubRegIndex(const SmallVector &); + getConcatSubRegIndex(const SmallVector &, + const CodeGenHwModes &CGH); const std::deque &getRegisters() const { return Registers; } diff --git a/llvm/utils/TableGen/Common/InfoByHwMode.cpp b/llvm/utils/TableGen/Common/InfoByHwMode.cpp index 5496408bb0d306..cacf4ece667137 100644 --- a/llvm/utils/TableGen/Common/InfoByHwMode.cpp +++ b/llvm/utils/TableGen/Common/InfoByHwMode.cpp @@ -183,6 +183,20 @@ void RegSizeInfoByHwMode::writeToStream(raw_ostream &OS) const { OS << '}'; } +SubRegRange::SubRegRange(Record *R) { + Size = R->getValueAsInt("Size"); + Offset = R->getValueAsInt("Offset"); +} + +SubRegRangeByHwMode::SubRegRangeByHwMode(Record *R, const CodeGenHwModes &CGH) { + const HwModeSelect &MS = CGH.getHwModeSelect(R); + for (const HwModeSelect::PairType &P : MS.Items) { + auto I = Map.insert({P.first, SubRegRange(P.second)}); + assert(I.second && "Duplicate entry?"); + (void)I; + } +} + EncodingInfoByHwMode::EncodingInfoByHwMode(Record *R, const CodeGenHwModes &CGH) { const HwModeSelect &MS = CGH.getHwModeSelect(R); diff --git a/llvm/utils/TableGen/Common/InfoByHwMode.h b/llvm/utils/TableGen/Common/InfoByHwMode.h index 1909913c50c6e0..dd0b9830d757e8 100644 --- a/llvm/utils/TableGen/Common/InfoByHwMode.h +++ b/llvm/utils/TableGen/Common/InfoByHwMode.h @@ -176,6 +176,8 @@ struct ValueTypeByHwMode : public InfoByHwMode { ValueTypeByHwMode getValueTypeByHwMode(Record *Rec, const CodeGenHwModes &CGH); +raw_ostream &operator<<(raw_ostream &OS, const ValueTypeByHwMode &T); + struct RegSizeInfo { unsigned RegSize; unsigned SpillSize; @@ -213,10 +215,27 @@ struct RegSizeInfoByHwMode : public InfoByHwMode { } }; -raw_ostream &operator<<(raw_ostream &OS, const ValueTypeByHwMode &T); raw_ostream &operator<<(raw_ostream &OS, const RegSizeInfo &T); raw_ostream &operator<<(raw_ostream &OS, const RegSizeInfoByHwMode &T); +struct SubRegRange { + uint16_t Size; + uint16_t Offset; + + SubRegRange(Record *R); + SubRegRange(uint16_t Size, uint16_t Offset) : Size(Size), Offset(Offset) {} +}; + +struct SubRegRangeByHwMode : public InfoByHwMode { + SubRegRangeByHwMode(Record *R, const CodeGenHwModes &CGH); + SubRegRangeByHwMode(SubRegRange Range) { Map.insert({DefaultMode, Range}); } + SubRegRangeByHwMode() = default; + + void insertSubRegRangeForMode(unsigned Mode, SubRegRange Info) { + Map.insert(std::pair(Mode, Info)); + } +}; + struct EncodingInfoByHwMode : public InfoByHwMode { EncodingInfoByHwMode(Record *R, const CodeGenHwModes &CGH); EncodingInfoByHwMode() = default; diff --git a/llvm/utils/TableGen/RegisterInfoEmitter.cpp b/llvm/utils/TableGen/RegisterInfoEmitter.cpp index a1259bff6ba8b0..ee8830edeedbbe 100644 --- a/llvm/utils/TableGen/RegisterInfoEmitter.cpp +++ b/llvm/utils/TableGen/RegisterInfoEmitter.cpp @@ -1245,10 +1245,13 @@ void RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, // Emit the table of sub-register index sizes. OS << "static const TargetRegisterInfo::SubRegCoveredBits " "SubRegIdxRangeTable[] = {\n"; - OS << " { " << (uint16_t)-1 << ", " << (uint16_t)-1 << " },\n"; - for (const auto &Idx : SubRegIndices) { - OS << " { " << Idx.Offset << ", " << Idx.Size << " },\t// " - << Idx.getName() << "\n"; + for (unsigned M = 0; M < NumModes; ++M) { + OS << " { " << (uint16_t)-1 << ", " << (uint16_t)-1 << " },\n"; + for (const auto &Idx : SubRegIndices) { + const SubRegRange &Range = Idx.Range.get(M); + OS << " { " << Range.Offset << ", " << Range.Size << " },\t// " + << Idx.getName() << "\n"; + } } OS << "};\n\n"; @@ -1864,7 +1867,13 @@ void RegisterInfoEmitter::debugDump(raw_ostream &OS) { OS << "SubRegIndex " << SRI.getName() << ":\n"; OS << "\tLaneMask: " << PrintLaneMask(SRI.LaneMask) << '\n'; OS << "\tAllSuperRegsCovered: " << SRI.AllSuperRegsCovered << '\n'; - OS << "\tOffset, Size: " << SRI.Offset << ", " << SRI.Size << '\n'; + OS << "\tOffset: {"; + for (unsigned M = 0; M != NumModes; ++M) + OS << ' ' << getModeName(M) << ':' << SRI.Range.get(M).Offset; + OS << " }\n\tSize: {"; + for (unsigned M = 0; M != NumModes; ++M) + OS << ' ' << getModeName(M) << ':' << SRI.Range.get(M).Size; + OS << " }\n"; } for (const CodeGenRegister &R : RegBank.getRegisters()) { From 10bd55566a01c63d9e4f46da5a4e671684aa7fc5 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Wed, 27 Mar 2024 12:20:24 -0700 Subject: [PATCH 5/5] [RISCV] Model vd as a src for some Zvk* instructions in MC layer. (#86710) Some Zvk instructions use vd as a source regardless of tail policy. Model this in the MC layer. We already do this for FMA for example. --- llvm/lib/Target/RISCV/RISCVInstrInfoV.td | 8 ---- llvm/lib/Target/RISCV/RISCVInstrInfoZvk.td | 52 ++++++++++++++++------ 2 files changed, 39 insertions(+), 21 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoV.td b/llvm/lib/Target/RISCV/RISCVInstrInfoV.td index 875f2e382d54fe..e68fb42ece9f02 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoV.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoV.td @@ -531,14 +531,6 @@ class VALUVs2 funct6, bits<5> vs1, RISCVVFormat opv, string opcodestr> : RVInstV; - -// op vd, vs2 (use vs1 as instruction encoding) -class VALUVs2NoVm funct6, bits<5> vs1, RISCVVFormat opv, string opcodestr> - : RVInstV { - let vm = 1; -} } // hasSideEffects = 0, mayLoad = 0, mayStore = 0 //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZvk.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZvk.td index b388bb00b0f2ed..60db03d68e4764 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoZvk.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZvk.td @@ -67,6 +67,16 @@ class PALUVVNoVm funct6, RISCVVFormat opv, string opcodestr> let Inst{6-0} = OPC_OP_P.Value; } +// op vd, vs2, vs1 +class PALUVVNoVmTernary funct6, RISCVVFormat opv, string opcodestr> + : RVInstVV { + let Constraints = "$vd = $vd_wb"; + let vm = 1; + let Inst{6-0} = OPC_OP_P.Value; +} + // op vd, vs2, imm class PALUVINoVm funct6, string opcodestr, Operand optype> : VALUVINoVm { @@ -74,18 +84,34 @@ class PALUVINoVm funct6, string opcodestr, Operand optype> let Inst{14-12} = OPMVV.Value; } -// op vd, vs2 (use vs1 as instruction encoding) -class PALUVs2NoVm funct6, bits<5> vs1, RISCVVFormat opv, string opcodestr> - : VALUVs2NoVm { +// op vd, vs2, imm where vd is also a source regardless of tail policy +class PALUVINoVmBinary funct6, string opcodestr, Operand optype> + : RVInstIVI { + let Constraints = "$vd = $vd_wb"; + let vm = 1; + let Inst{6-0} = OPC_OP_P.Value; + let Inst{14-12} = OPMVV.Value; +} + +// op vd, vs2 (use vs1 as instruction encoding) where vd is also a source +// regardless of tail policy +class PALUVs2NoVmBinary funct6, bits<5> vs1, RISCVVFormat opv, + string opcodestr> + : RVInstV { + let Constraints = "$vd = $vd_wb"; + let vm = 1; let Inst{6-0} = OPC_OP_P.Value; } multiclass VAES_MV_V_S funct6_vv, bits<6> funct6_vs, bits<5> vs1, RISCVVFormat opv, string opcodestr> { let RVVConstraint = NoConstraint in - def NAME # _VV : PALUVs2NoVm; + def NAME # _VV : PALUVs2NoVmBinary; let RVVConstraint = VS2Constraint in - def NAME # _VS : PALUVs2NoVm; + def NAME # _VS : PALUVs2NoVmBinary; } } // hasSideEffects = 0, mayLoad = 0, mayStore = 0 @@ -116,14 +142,14 @@ let Predicates = [HasStdExtZvkb] in { } // Predicates = [HasStdExtZvkb] let Predicates = [HasStdExtZvkg], RVVConstraint = NoConstraint in { - def VGHSH_VV : PALUVVNoVm<0b101100, OPMVV, "vghsh.vv">; - def VGMUL_VV : PALUVs2NoVm<0b101000, 0b10001, OPMVV, "vgmul.vv">; + def VGHSH_VV : PALUVVNoVmTernary<0b101100, OPMVV, "vghsh.vv">; + def VGMUL_VV : PALUVs2NoVmBinary<0b101000, 0b10001, OPMVV, "vgmul.vv">; } // Predicates = [HasStdExtZvkg] let Predicates = [HasStdExtZvknhaOrZvknhb], RVVConstraint = Sha2Constraint in { - def VSHA2CH_VV : PALUVVNoVm<0b101110, OPMVV, "vsha2ch.vv">; - def VSHA2CL_VV : PALUVVNoVm<0b101111, OPMVV, "vsha2cl.vv">; - def VSHA2MS_VV : PALUVVNoVm<0b101101, OPMVV, "vsha2ms.vv">; + def VSHA2CH_VV : PALUVVNoVmTernary<0b101110, OPMVV, "vsha2ch.vv">; + def VSHA2CL_VV : PALUVVNoVmTernary<0b101111, OPMVV, "vsha2cl.vv">; + def VSHA2MS_VV : PALUVVNoVmTernary<0b101101, OPMVV, "vsha2ms.vv">; } // Predicates = [HasStdExtZvknhaOrZvknhb] let Predicates = [HasStdExtZvkned]in { @@ -132,9 +158,9 @@ let Predicates = [HasStdExtZvkned]in { defm VAESEF : VAES_MV_V_S<0b101000, 0b101001, 0b00011, OPMVV, "vaesef">; defm VAESEM : VAES_MV_V_S<0b101000, 0b101001, 0b00010, OPMVV, "vaesem">; def VAESKF1_VI : PALUVINoVm<0b100010, "vaeskf1.vi", uimm5>; - def VAESKF2_VI : PALUVINoVm<0b101010, "vaeskf2.vi", uimm5>; + def VAESKF2_VI : PALUVINoVmBinary<0b101010, "vaeskf2.vi", uimm5>; let RVVConstraint = VS2Constraint in - def VAESZ_VS : PALUVs2NoVm<0b101001, 0b00111, OPMVV, "vaesz.vs">; + def VAESZ_VS : PALUVs2NoVmBinary<0b101001, 0b00111, OPMVV, "vaesz.vs">; } // Predicates = [HasStdExtZvkned] let Predicates = [HasStdExtZvksed] in { @@ -144,7 +170,7 @@ let Predicates = [HasStdExtZvksed] in { } // Predicates = [HasStdExtZvksed] let Predicates = [HasStdExtZvksh], RVVConstraint = VS2Constraint in { - def VSM3C_VI : PALUVINoVm<0b101011, "vsm3c.vi", uimm5>; + def VSM3C_VI : PALUVINoVmBinary<0b101011, "vsm3c.vi", uimm5>; def VSM3ME_VV : PALUVVNoVm<0b100000, OPMVV, "vsm3me.vv">; } // Predicates = [HasStdExtZvksh]