diff options
Diffstat (limited to 'llvm/unittests')
28 files changed, 972 insertions, 120 deletions
diff --git a/llvm/unittests/ADT/STLExtrasTest.cpp b/llvm/unittests/ADT/STLExtrasTest.cpp index 47469983..966b1f0 100644 --- a/llvm/unittests/ADT/STLExtrasTest.cpp +++ b/llvm/unittests/ADT/STLExtrasTest.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -27,6 +28,7 @@ using namespace llvm; using testing::ElementsAre; +using testing::ElementsAreArray; using testing::UnorderedElementsAre; namespace { @@ -772,48 +774,30 @@ TEST(STLExtrasTest, DropBeginTest) { SmallVector<int, 5> vec{0, 1, 2, 3, 4}; for (int n = 0; n < 5; ++n) { - int i = n; - for (auto &v : drop_begin(vec, n)) { - EXPECT_EQ(v, i); - i += 1; - } - EXPECT_EQ(i, 5); + EXPECT_THAT(drop_begin(vec, n), + ElementsAreArray(ArrayRef(&vec[n], vec.size() - n))); } } TEST(STLExtrasTest, DropBeginDefaultTest) { SmallVector<int, 5> vec{0, 1, 2, 3, 4}; - int i = 1; - for (auto &v : drop_begin(vec)) { - EXPECT_EQ(v, i); - i += 1; - } - EXPECT_EQ(i, 5); + EXPECT_THAT(drop_begin(vec), ElementsAre(1, 2, 3, 4)); } TEST(STLExtrasTest, DropEndTest) { SmallVector<int, 5> vec{0, 1, 2, 3, 4}; for (int n = 0; n < 5; ++n) { - int i = 0; - for (auto &v : drop_end(vec, n)) { - EXPECT_EQ(v, i); - i += 1; - } - EXPECT_EQ(i, 5 - n); + EXPECT_THAT(drop_end(vec, n), + ElementsAreArray(ArrayRef(vec.data(), vec.size() - n))); } } TEST(STLExtrasTest, DropEndDefaultTest) { SmallVector<int, 5> vec{0, 1, 2, 3, 4}; - int i = 0; - for (auto &v : drop_end(vec)) { - EXPECT_EQ(v, i); - i += 1; - } - EXPECT_EQ(i, 4); + EXPECT_THAT(drop_end(vec), ElementsAre(0, 1, 2, 3)); } TEST(STLExtrasTest, MapRangeTest) { diff --git a/llvm/unittests/ADT/SmallVectorTest.cpp b/llvm/unittests/ADT/SmallVectorTest.cpp index e2e778f..1a01f30 100644 --- a/llvm/unittests/ADT/SmallVectorTest.cpp +++ b/llvm/unittests/ADT/SmallVectorTest.cpp @@ -13,6 +13,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/Support/Compiler.h" +#include "gmock/gmock.h" #include "gtest/gtest.h" #include <list> #include <stdarg.h> @@ -599,6 +600,15 @@ TYPED_TEST(SmallVectorTest, AssignSmallVector) { assertValuesInOrder(V, 2u, 7, 7); } +TYPED_TEST(SmallVectorTest, AssignArrayRef) { + SCOPED_TRACE("AssignArrayRef"); + auto &V = this->theVector; + Constructable Other[] = {7, 8, 9}; + V.push_back(Constructable(1)); + V.assign(ArrayRef(Other)); + assertValuesInOrder(V, 3u, 7, 8, 9); +} + // Move-assign test TYPED_TEST(SmallVectorTest, MoveAssignTest) { SCOPED_TRACE("MoveAssignTest"); @@ -1147,6 +1157,17 @@ TEST(SmallVectorTest, InitializerList) { EXPECT_TRUE(ArrayRef(V2).equals({4, 5, 3, 2})); } +namespace namespace_with_adl { +struct MyVector { + std::vector<int> data; +}; + +std::vector<int>::const_iterator begin(const MyVector &V) { + return V.data.begin(); +} +std::vector<int>::const_iterator end(const MyVector &V) { return V.data.end(); } +} // namespace namespace_with_adl + TEST(SmallVectorTest, ToVector) { { std::vector<char> v = {'a', 'b', 'c'}; @@ -1164,6 +1185,15 @@ TEST(SmallVectorTest, ToVector) { for (size_t I = 0; I < v.size(); ++I) EXPECT_EQ(v[I], Vector[I]); } + { + // Check that to_vector and to_vector_of work with types that require ADL + // for being/end iterators. + namespace_with_adl::MyVector V = {{1, 2, 3}}; + auto IntVector = to_vector(V); + EXPECT_THAT(IntVector, testing::ElementsAre(1, 2, 3)); + IntVector = to_vector<3>(V); + EXPECT_THAT(IntVector, testing::ElementsAre(1, 2, 3)); + } } struct To { @@ -1222,6 +1252,15 @@ TEST(SmallVectorTest, ToVectorOf) { for (size_t I = 0; I < StdVector.size(); ++I) EXPECT_EQ(StdVector[I], Vector[I]); } + { + // Check that to_vector works with types that require ADL for being/end + // iterators. + namespace_with_adl::MyVector V = {{1, 2, 3}}; + auto UnsignedVector = to_vector_of<unsigned>(V); + EXPECT_THAT(UnsignedVector, testing::ElementsAre(1u, 2u, 3u)); + UnsignedVector = to_vector_of<unsigned, 3>(V); + EXPECT_THAT(UnsignedVector, testing::ElementsAre(1u, 2u, 3u)); + } } template <class VectorT> diff --git a/llvm/unittests/Analysis/MemoryProfileInfoTest.cpp b/llvm/unittests/Analysis/MemoryProfileInfoTest.cpp index d1c0f64..113b052 100644 --- a/llvm/unittests/Analysis/MemoryProfileInfoTest.cpp +++ b/llvm/unittests/Analysis/MemoryProfileInfoTest.cpp @@ -638,7 +638,7 @@ declare dso_local noalias noundef i8* @malloc(i64 noundef) !0 = !{!1, !3, !5, !7, !9, !11} !1 = !{!2, !"cold"} !2 = !{i64 1, i64 2, i64 3} -!3 = !{!4, !"cold"} +!3 = !{!4, !"cold", !13} !4 = !{i64 1, i64 2, i64 4} !5 = !{!6, !"notcold"} !6 = !{i64 1, i64 5, i64 6} @@ -648,6 +648,7 @@ declare dso_local noalias noundef i8* @malloc(i64 noundef) !10 = !{i64 1, i64 8, i64 9} !11 = !{!12, !"hot"} !12 = !{i64 1, i64 8, i64 10} +!13 = !{i64 123, i64 456} )IR"); Function *Func = M->getFunction("test"); @@ -683,10 +684,25 @@ declare dso_local noalias noundef i8* @malloc(i64 noundef) auto *StackId = mdconst::dyn_extract<ConstantInt>(StackMD->getOperand(0)); EXPECT_EQ(StackId->getZExtValue(), 1u); StackId = mdconst::dyn_extract<ConstantInt>(StackMD->getOperand(1)); - if (StackId->getZExtValue() == 2u) + if (StackId->getZExtValue() == 2u) { EXPECT_EQ(getMIBAllocType(MIB), AllocationType::Cold); - else if (StackId->getZExtValue() == 5u) + // We should propagate the single context size info from the second cold + // context above onto the new merged/trimmed context. + ASSERT_EQ(MIB->getNumOperands(), 3u); + MDNode *ContextSizePair = dyn_cast<MDNode>(MIB->getOperand(2)); + assert(ContextSizePair->getNumOperands() == 2); + EXPECT_EQ( + mdconst::dyn_extract<ConstantInt>(ContextSizePair->getOperand(0)) + ->getZExtValue(), + 123u); + EXPECT_EQ( + mdconst::dyn_extract<ConstantInt>(ContextSizePair->getOperand(1)) + ->getZExtValue(), + 456u); + } else if (StackId->getZExtValue() == 5u) { EXPECT_EQ(getMIBAllocType(MIB), AllocationType::NotCold); + ASSERT_EQ(MIB->getNumOperands(), 2u); + } } } diff --git a/llvm/unittests/AsmParser/AsmParserTest.cpp b/llvm/unittests/AsmParser/AsmParserTest.cpp index ce22670..898a829 100644 --- a/llvm/unittests/AsmParser/AsmParserTest.cpp +++ b/llvm/unittests/AsmParser/AsmParserTest.cpp @@ -6,7 +6,9 @@ // //===----------------------------------------------------------------------===// +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" +#include "llvm/AsmParser/AsmParserContext.h" #include "llvm/AsmParser/Parser.h" #include "llvm/AsmParser/SlotMapping.h" #include "llvm/IR/Constants.h" @@ -14,10 +16,14 @@ #include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" +#include "llvm/IR/Value.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/Error.h" #include "llvm/Support/SourceMgr.h" #include "gtest/gtest.h" +#define DEBUG_TYPE "unittest-asm-parser-tests" + using namespace llvm; namespace { @@ -479,4 +485,53 @@ TEST(AsmParserTest, DIExpressionBodyAtBeginningWithSlotMappingParsing) { ASSERT_EQ(Mapping.MetadataNodes.size(), 0u); } +#define ASSERT_EQ_LOC(Loc1, Loc2) \ + do { \ + EXPECT_TRUE(Loc1.contains(Loc2) && Loc2.contains(Loc1)) \ + << #Loc1 " location: " << Loc1.Start.Line << ":" << Loc1.Start.Col \ + << " - " << Loc1.End.Line << ":" << Loc1.End.Col << "\n" \ + << #Loc2 " location: " << Loc2.Start.Line << ":" << Loc2.Start.Col \ + << " - " << Loc2.End.Line << ":" << Loc2.End.Col << "\n"; \ + } while (false) + +TEST(AsmParserTest, ParserObjectLocations) { + StringRef Source = "define i32 @main() {\n" + "entry:\n" + " %a = add i32 1, 2\n" + " ret i32 %a\n" + "}\n"; + LLVMContext Ctx; + SMDiagnostic Error; + SlotMapping Mapping; + AsmParserContext ParserContext; + auto Mod = parseAssemblyString(Source, Error, Ctx, &Mapping, &ParserContext); + + auto *MainFn = Mod->getFunction("main"); + ASSERT_TRUE(MainFn != nullptr); + + auto MaybeMainLoc = ParserContext.getFunctionLocation(MainFn); + EXPECT_TRUE(MaybeMainLoc.has_value()); + auto MainLoc = MaybeMainLoc.value(); + auto ExpectedMainLoc = FileLocRange(FileLoc{0, 0}, FileLoc{4, 1}); + ASSERT_EQ_LOC(MainLoc, ExpectedMainLoc); + + auto &EntryBB = MainFn->getEntryBlock(); + auto MaybeEntryBBLoc = ParserContext.getBlockLocation(&EntryBB); + ASSERT_TRUE(MaybeEntryBBLoc.has_value()); + auto EntryBBLoc = MaybeEntryBBLoc.value(); + auto ExpectedEntryBBLoc = FileLocRange(FileLoc{1, 0}, FileLoc{3, 14}); + ASSERT_EQ_LOC(EntryBBLoc, ExpectedEntryBBLoc); + + SmallVector<FileLocRange> InstructionLocations = { + FileLocRange(FileLoc{2, 4}, FileLoc{2, 21}), + FileLocRange(FileLoc{3, 4}, FileLoc{3, 14})}; + + for (const auto &[Inst, ExpectedLoc] : zip(EntryBB, InstructionLocations)) { + auto MaybeInstLoc = ParserContext.getInstructionLocation(&Inst); + ASSERT_TRUE(MaybeMainLoc.has_value()); + auto InstLoc = MaybeInstLoc.value(); + ASSERT_EQ_LOC(InstLoc, ExpectedLoc); + } +} + } // end anonymous namespace diff --git a/llvm/unittests/CAS/CASTestConfig.cpp b/llvm/unittests/CAS/CASTestConfig.cpp index 91d0970..10e4b68 100644 --- a/llvm/unittests/CAS/CASTestConfig.cpp +++ b/llvm/unittests/CAS/CASTestConfig.cpp @@ -9,6 +9,7 @@ #include "CASTestConfig.h" #include "llvm/CAS/ObjectStore.h" #include "gtest/gtest.h" +#include <mutex> using namespace llvm; using namespace llvm::cas; diff --git a/llvm/unittests/CAS/OnDiskCommonUtils.h b/llvm/unittests/CAS/OnDiskCommonUtils.h index 57c8c22..89f93e0 100644 --- a/llvm/unittests/CAS/OnDiskCommonUtils.h +++ b/llvm/unittests/CAS/OnDiskCommonUtils.h @@ -45,7 +45,7 @@ inline HashType digest(StringRef Data) { } inline ValueType valueFromString(StringRef S) { - ValueType Val; + ValueType Val = {}; llvm::copy(S.substr(0, sizeof(Val)), Val.data()); return Val; } diff --git a/llvm/unittests/CAS/OnDiskGraphDBTest.cpp b/llvm/unittests/CAS/OnDiskGraphDBTest.cpp index 58f5dcc6..3c2e963 100644 --- a/llvm/unittests/CAS/OnDiskGraphDBTest.cpp +++ b/llvm/unittests/CAS/OnDiskGraphDBTest.cpp @@ -283,7 +283,7 @@ TEST_F(OnDiskCASTest, OnDiskGraphDBFaultInPolicyConflict) { OnDiskGraphDB::FaultInPolicy::SingleNode); } -#if defined(EXPENSIVE_CHECKS) +#if defined(EXPENSIVE_CHECKS) && !defined(_WIN32) TEST_F(OnDiskCASTest, OnDiskGraphDBSpaceLimit) { setMaxOnDiskCASMappingSize(); unittest::TempDir Temp("ondiskcas", /*Unique=*/true); diff --git a/llvm/unittests/CAS/OnDiskKeyValueDBTest.cpp b/llvm/unittests/CAS/OnDiskKeyValueDBTest.cpp index 89c03b8..41512d0 100644 --- a/llvm/unittests/CAS/OnDiskKeyValueDBTest.cpp +++ b/llvm/unittests/CAS/OnDiskKeyValueDBTest.cpp @@ -33,13 +33,13 @@ TEST_F(OnDiskCASTest, OnDiskKeyValueDBTest) { } ValueType ValW = valueFromString("world"); - ArrayRef<char> Val; + std::optional<ArrayRef<char>> Val; ASSERT_THAT_ERROR(DB->put(digest("hello"), ValW).moveInto(Val), Succeeded()); - EXPECT_EQ(Val, ArrayRef(ValW)); + EXPECT_EQ(*Val, ArrayRef(ValW)); ASSERT_THAT_ERROR( DB->put(digest("hello"), valueFromString("other")).moveInto(Val), Succeeded()); - EXPECT_EQ(Val, ArrayRef(ValW)); + EXPECT_EQ(*Val, ArrayRef(ValW)); { std::optional<ArrayRef<char>> Val; @@ -65,7 +65,7 @@ TEST_F(OnDiskCASTest, OnDiskKeyValueDBTest) { // Insert a lot of entries. for (unsigned I = 0; I < 1024 * 100; ++I) { std::string Index = Twine(I).str(); - ArrayRef<char> Val; + std::optional<ArrayRef<char>> Val; ASSERT_THAT_ERROR( DB->put(digest(Index), valueFromString(Index)).moveInto(Val), Succeeded()); diff --git a/llvm/unittests/CodeGen/AsmPrinterDwarfTest.cpp b/llvm/unittests/CodeGen/AsmPrinterDwarfTest.cpp index 6c08173..af2d56d 100644 --- a/llvm/unittests/CodeGen/AsmPrinterDwarfTest.cpp +++ b/llvm/unittests/CodeGen/AsmPrinterDwarfTest.cpp @@ -383,14 +383,14 @@ class AsmPrinterHandlerTest : public AsmPrinterFixtureBase { public: TestHandler(AsmPrinterHandlerTest &Test) : Test(Test) {} - virtual ~TestHandler() {} - virtual void setSymbolSize(const MCSymbol *Sym, uint64_t Size) override {} - virtual void beginModule(Module *M) override { Test.BeginCount++; } - virtual void endModule() override { Test.EndCount++; } - virtual void beginFunction(const MachineFunction *MF) override {} - virtual void endFunction(const MachineFunction *MF) override {} - virtual void beginInstruction(const MachineInstr *MI) override {} - virtual void endInstruction() override {} + ~TestHandler() override {} + void setSymbolSize(const MCSymbol *Sym, uint64_t Size) override {} + void beginModule(Module *M) override { Test.BeginCount++; } + void endModule() override { Test.EndCount++; } + void beginFunction(const MachineFunction *MF) override {} + void endFunction(const MachineFunction *MF) override {} + void beginInstruction(const MachineInstr *MI) override {} + void endInstruction() override {} }; protected: diff --git a/llvm/unittests/CodeGen/InstrRefLDVTest.cpp b/llvm/unittests/CodeGen/InstrRefLDVTest.cpp index ce2a38b..ff87e7b 100644 --- a/llvm/unittests/CodeGen/InstrRefLDVTest.cpp +++ b/llvm/unittests/CodeGen/InstrRefLDVTest.cpp @@ -69,7 +69,7 @@ public: InstrRefLDVTest() : Ctx(), Mod(std::make_unique<Module>("beehives", Ctx)) {} - void SetUp() { + void SetUp() override { // Boilerplate that creates a MachineFunction and associated blocks. Mod->setDataLayout("e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-" diff --git a/llvm/unittests/CodeGen/MIR2VecTest.cpp b/llvm/unittests/CodeGen/MIR2VecTest.cpp index 11222b4..d42749c 100644 --- a/llvm/unittests/CodeGen/MIR2VecTest.cpp +++ b/llvm/unittests/CodeGen/MIR2VecTest.cpp @@ -54,6 +54,9 @@ protected: std::unique_ptr<Module> M; std::unique_ptr<TargetMachine> TM; const TargetInstrInfo *TII = nullptr; + const TargetRegisterInfo *TRI = nullptr; + std::unique_ptr<MachineModuleInfo> MMI; + MachineFunction *MF = nullptr; static void SetUpTestCase() { InitializeAllTargets(); @@ -82,31 +85,131 @@ protected: return; } + // Set the data layout to match the target machine + M->setDataLayout(TM->createDataLayout()); + // Create a dummy function to get subtarget info FunctionType *FT = FunctionType::get(Type::getVoidTy(*Ctx), false); Function *F = Function::Create(FT, Function::ExternalLinkage, "test", M.get()); - // Get the target instruction info + // Create MMI and MF to get TRI and MRI + MMI = std::make_unique<MachineModuleInfo>(TM.get()); + MF = &MMI->getOrCreateMachineFunction(*F); + + // Get the target instruction info and register info TII = TM->getSubtargetImpl(*F)->getInstrInfo(); - if (!TII) { - GTEST_SKIP() << "Failed to get target instruction info; Skipping test"; + TRI = TM->getSubtargetImpl(*F)->getRegisterInfo(); + if (!TII || !TRI) { + GTEST_SKIP() + << "Failed to get target instruction/register info; Skipping test"; return; } } - void TearDown() override { TII = nullptr; } + void TearDown() override { + TII = nullptr; + TRI = nullptr; + } + + // Find an opcode by name + int findOpcodeByName(StringRef Name) { + for (unsigned Opcode = 1; Opcode < TII->getNumOpcodes(); ++Opcode) { + if (TII->getName(Opcode) == Name) + return Opcode; + } + return -1; // Not found + } + + // Create a vocabulary with specific opcodes and embeddings + // This might cause errors in future when the validation in + // MIRVocabulary::generateStorage() enforces hard checks on the vocabulary + // entries. + Expected<MIRVocabulary> createTestVocab( + std::initializer_list<std::pair<const char *, float>> Opcodes, + std::initializer_list<std::pair<const char *, float>> CommonOperands, + std::initializer_list<std::pair<const char *, float>> PhyRegs, + std::initializer_list<std::pair<const char *, float>> VirtRegs, + unsigned Dimension = 2) { + assert(TII && TRI && MF && "Target info not initialized"); + VocabMap OpcodeMap, CommonOperandMap, PhyRegMap, VirtRegMap; + for (const auto &[Name, Value] : Opcodes) + OpcodeMap[Name] = Embedding(Dimension, Value); + + for (const auto &[Name, Value] : CommonOperands) + CommonOperandMap[Name] = Embedding(Dimension, Value); + + for (const auto &[Name, Value] : PhyRegs) + PhyRegMap[Name] = Embedding(Dimension, Value); + + for (const auto &[Name, Value] : VirtRegs) + VirtRegMap[Name] = Embedding(Dimension, Value); + + // If any section is empty, create minimal maps for other vocabulary + // sections to satisfy validation + if (Opcodes.size() == 0) + OpcodeMap["NOOP"] = Embedding(Dimension, 0.0f); + if (CommonOperands.size() == 0) + CommonOperandMap["Immediate"] = Embedding(Dimension, 0.0f); + if (PhyRegs.size() == 0) + PhyRegMap["GR32"] = Embedding(Dimension, 0.0f); + if (VirtRegs.size() == 0) + VirtRegMap["GR32"] = Embedding(Dimension, 0.0f); + + return MIRVocabulary::create( + std::move(OpcodeMap), std::move(CommonOperandMap), std::move(PhyRegMap), + std::move(VirtRegMap), *TII, *TRI, MF->getRegInfo()); + } }; -// Function to find an opcode by name -static int findOpcodeByName(const TargetInstrInfo *TII, StringRef Name) { - for (unsigned Opcode = 1; Opcode < TII->getNumOpcodes(); ++Opcode) { - if (TII->getName(Opcode) == Name) - return Opcode; +// Parameterized test for empty vocab sections +class MIR2VecVocabEmptySectionTestFixture + : public MIR2VecVocabTestFixture, + public ::testing::WithParamInterface<int> { +protected: + void SetUp() override { + MIR2VecVocabTestFixture::SetUp(); + // If base class setup was skipped (TII not initialized), skip derived setup + if (!TII) + GTEST_SKIP() << "Failed to get target instruction info in " + "the base class setup; Skipping test"; + } +}; + +TEST_P(MIR2VecVocabEmptySectionTestFixture, EmptySectionFailsValidation) { + int EmptySection = GetParam(); + VocabMap OpcodeMap, CommonOperandMap, PhyRegMap, VirtRegMap; + + if (EmptySection != 0) + OpcodeMap["ADD"] = Embedding(2, 1.0f); + if (EmptySection != 1) + CommonOperandMap["Immediate"] = Embedding(2, 0.0f); + if (EmptySection != 2) + PhyRegMap["GR32"] = Embedding(2, 0.0f); + if (EmptySection != 3) + VirtRegMap["GR32"] = Embedding(2, 0.0f); + + ASSERT_TRUE(TII != nullptr); + ASSERT_TRUE(TRI != nullptr); + ASSERT_TRUE(MF != nullptr); + + auto VocabOrErr = MIRVocabulary::create( + std::move(OpcodeMap), std::move(CommonOperandMap), std::move(PhyRegMap), + std::move(VirtRegMap), *TII, *TRI, MF->getRegInfo()); + EXPECT_FALSE(static_cast<bool>(VocabOrErr)) + << "Factory method should fail when section " << EmptySection + << " is empty"; + + if (!VocabOrErr) { + auto Err = VocabOrErr.takeError(); + std::string ErrorMsg = toString(std::move(Err)); + EXPECT_FALSE(ErrorMsg.empty()); } - return -1; // Not found } +INSTANTIATE_TEST_SUITE_P(EmptySection, MIR2VecVocabEmptySectionTestFixture, + ::testing::Values(0, 1, 2, 3)); + TEST_F(MIR2VecVocabTestFixture, CanonicalOpcodeMappingTest) { // Test that same base opcodes get same canonical indices std::string BaseName1 = MIRVocabulary::extractBaseOpcodeName("ADD16ri"); @@ -118,10 +221,8 @@ TEST_F(MIR2VecVocabTestFixture, CanonicalOpcodeMappingTest) { // Create a MIRVocabulary instance to test the mapping // Use a minimal MIRVocabulary to trigger canonical mapping construction - VocabMap VMap; Embedding Val = Embedding(64, 1.0f); - VMap["ADD"] = Val; - auto TestVocabOrErr = MIRVocabulary::create(std::move(VMap), *TII); + auto TestVocabOrErr = createTestVocab({{"ADD", 1.0f}}, {}, {}, {}, 64); ASSERT_TRUE(static_cast<bool>(TestVocabOrErr)) << "Failed to create vocabulary: " << toString(TestVocabOrErr.takeError()); @@ -156,16 +257,16 @@ TEST_F(MIR2VecVocabTestFixture, CanonicalOpcodeMappingTest) { 6880u); // X86 has >6880 unique base opcodes // Check that the embeddings for opcodes not in the vocab are zero vectors - int Add32rrOpcode = findOpcodeByName(TII, "ADD32rr"); + int Add32rrOpcode = findOpcodeByName("ADD32rr"); ASSERT_NE(Add32rrOpcode, -1) << "ADD32rr opcode not found"; EXPECT_TRUE(TestVocab[Add32rrOpcode].approximatelyEquals(Val)); - int Sub32rrOpcode = findOpcodeByName(TII, "SUB32rr"); + int Sub32rrOpcode = findOpcodeByName("SUB32rr"); ASSERT_NE(Sub32rrOpcode, -1) << "SUB32rr opcode not found"; EXPECT_TRUE( TestVocab[Sub32rrOpcode].approximatelyEquals(Embedding(64, 0.0f))); - int Mov32rrOpcode = findOpcodeByName(TII, "MOV32rr"); + int Mov32rrOpcode = findOpcodeByName("MOV32rr"); ASSERT_NE(Mov32rrOpcode, -1) << "MOV32rr opcode not found"; EXPECT_TRUE( TestVocab[Mov32rrOpcode].approximatelyEquals(Embedding(64, 0.0f))); @@ -178,9 +279,7 @@ TEST_F(MIR2VecVocabTestFixture, DeterministicMapping) { // Create a MIRVocabulary instance to test deterministic mapping // Use a minimal MIRVocabulary to trigger canonical mapping construction - VocabMap VMap; - VMap["ADD"] = Embedding(64, 1.0f); - auto TestVocabOrErr = MIRVocabulary::create(std::move(VMap), *TII); + auto TestVocabOrErr = createTestVocab({{"ADD", 1.0f}}, {}, {}, {}, 64); ASSERT_TRUE(static_cast<bool>(TestVocabOrErr)) << "Failed to create vocabulary: " << toString(TestVocabOrErr.takeError()); @@ -189,8 +288,6 @@ TEST_F(MIR2VecVocabTestFixture, DeterministicMapping) { unsigned Index1 = TestVocab.getCanonicalIndexForBaseName(BaseName); unsigned Index2 = TestVocab.getCanonicalIndexForBaseName(BaseName); unsigned Index3 = TestVocab.getCanonicalIndexForBaseName(BaseName); - - EXPECT_EQ(Index1, Index2); EXPECT_EQ(Index2, Index3); // Test across multiple runs @@ -202,11 +299,8 @@ TEST_F(MIR2VecVocabTestFixture, DeterministicMapping) { // Test MIRVocabulary construction TEST_F(MIR2VecVocabTestFixture, VocabularyConstruction) { - VocabMap VMap; - VMap["ADD"] = Embedding(128, 1.0f); // Dimension 128, all values 1.0 - VMap["SUB"] = Embedding(128, 2.0f); // Dimension 128, all values 2.0 - - auto VocabOrErr = MIRVocabulary::create(std::move(VMap), *TII); + auto VocabOrErr = + createTestVocab({{"ADD", 1.0f}, {"SUB", 2.0f}}, {}, {}, {}, 128); ASSERT_TRUE(static_cast<bool>(VocabOrErr)) << "Failed to create vocabulary: " << toString(VocabOrErr.takeError()); auto &Vocab = *VocabOrErr; @@ -227,20 +321,450 @@ TEST_F(MIR2VecVocabTestFixture, VocabularyConstruction) { EXPECT_GT(Count, 0u); } -// Test factory method with empty vocabulary -TEST_F(MIR2VecVocabTestFixture, EmptyVocabularyCreation) { - VocabMap EmptyVMap; +// Fixture for embedding related tests +class MIR2VecEmbeddingTestFixture : public MIR2VecVocabTestFixture { +protected: + void SetUp() override { + MIR2VecVocabTestFixture::SetUp(); + // If base class setup was skipped (TII not initialized), skip derived setup + if (!TII) + GTEST_SKIP() << "Failed to get target instruction info in " + "the base class setup; Skipping test"; + } - auto VocabOrErr = MIRVocabulary::create(std::move(EmptyVMap), *TII); - EXPECT_FALSE(static_cast<bool>(VocabOrErr)) - << "Factory method should fail with empty vocabulary"; + void TearDown() override { MIR2VecVocabTestFixture::TearDown(); } - // Consume the error - if (!VocabOrErr) { - auto Err = VocabOrErr.takeError(); - std::string ErrorMsg = toString(std::move(Err)); - EXPECT_FALSE(ErrorMsg.empty()); + // Create a machine instruction + MachineInstr *createMachineInstr(MachineBasicBlock &MBB, unsigned Opcode) { + const MCInstrDesc &Desc = TII->get(Opcode); + // Create instruction - operands don't affect opcode-based embeddings + MachineInstr *MI = BuildMI(MBB, MBB.end(), DebugLoc(), Desc); + return MI; + } + + MachineInstr *createMachineInstr(MachineBasicBlock &MBB, + const char *OpcodeName) { + int Opcode = findOpcodeByName(OpcodeName); + if (Opcode == -1) + return nullptr; + return createMachineInstr(MBB, Opcode); + } + + void createMachineInstrs(MachineBasicBlock &MBB, + std::initializer_list<const char *> Opcodes) { + for (const char *OpcodeName : Opcodes) { + MachineInstr *MI = createMachineInstr(MBB, OpcodeName); + ASSERT_TRUE(MI != nullptr); + } + } +}; + +// Test factory method for creating embedder +TEST_F(MIR2VecEmbeddingTestFixture, CreateSymbolicEmbedder) { + auto VocabOrErr = + MIRVocabulary::createDummyVocabForTest(*TII, *TRI, MF->getRegInfo(), 1); + ASSERT_TRUE(static_cast<bool>(VocabOrErr)) + << "Failed to create vocabulary: " << toString(VocabOrErr.takeError()); + auto &V = *VocabOrErr; + auto Emb = MIREmbedder::create(MIR2VecKind::Symbolic, *MF, V); + EXPECT_NE(Emb, nullptr); +} + +TEST_F(MIR2VecEmbeddingTestFixture, CreateInvalidMode) { + auto VocabOrErr = + MIRVocabulary::createDummyVocabForTest(*TII, *TRI, MF->getRegInfo(), 1); + ASSERT_TRUE(static_cast<bool>(VocabOrErr)) + << "Failed to create vocabulary: " << toString(VocabOrErr.takeError()); + auto &V = *VocabOrErr; + auto Result = MIREmbedder::create(static_cast<MIR2VecKind>(-1), *MF, V); + EXPECT_FALSE(static_cast<bool>(Result)); +} + +// Test SymbolicMIREmbedder with simple target opcodes +TEST_F(MIR2VecEmbeddingTestFixture, TestSymbolicEmbedder) { + // Create a test vocabulary with specific values + auto VocabOrErr = createTestVocab( + { + {"NOOP", 1.0f}, // [1.0, 1.0, 1.0, 1.0] + {"RET", 2.0f}, // [2.0, 2.0, 2.0, 2.0] + {"TRAP", 3.0f} // [3.0, 3.0, 3.0, 3.0] + }, + {}, {}, {}, 4); + ASSERT_TRUE(static_cast<bool>(VocabOrErr)) + << "Failed to create vocabulary: " << toString(VocabOrErr.takeError()); + auto &Vocab = *VocabOrErr; + // Create a basic block using fixture's MF + MachineBasicBlock *MBB = MF->CreateMachineBasicBlock(); + MF->push_back(MBB); + + // Use real X86 opcodes that should exist and not be pseudo + auto NoopInst = createMachineInstr(*MBB, "NOOP"); + ASSERT_TRUE(NoopInst != nullptr); + + auto RetInst = createMachineInstr(*MBB, "RET64"); + ASSERT_TRUE(RetInst != nullptr); + + auto TrapInst = createMachineInstr(*MBB, "TRAP"); + ASSERT_TRUE(TrapInst != nullptr); + + // Verify these are not pseudo instructions + ASSERT_FALSE(NoopInst->isPseudo()) << "NOOP is marked as pseudo instruction"; + ASSERT_FALSE(RetInst->isPseudo()) << "RET is marked as pseudo instruction"; + ASSERT_FALSE(TrapInst->isPseudo()) << "TRAP is marked as pseudo instruction"; + + // Create embedder + auto Embedder = SymbolicMIREmbedder::create(*MF, Vocab); + ASSERT_TRUE(Embedder != nullptr); + + // Test instruction embeddings + auto NoopEmb = Embedder->getMInstVector(*NoopInst); + auto RetEmb = Embedder->getMInstVector(*RetInst); + auto TrapEmb = Embedder->getMInstVector(*TrapInst); + + // Verify embeddings match expected values (accounting for weight scaling) + float ExpectedWeight = mir2vec::OpcWeight; // Global weight from command line + EXPECT_TRUE(NoopEmb.approximatelyEquals(Embedding(4, 1.0f * ExpectedWeight))); + EXPECT_TRUE(RetEmb.approximatelyEquals(Embedding(4, 2.0f * ExpectedWeight))); + EXPECT_TRUE(TrapEmb.approximatelyEquals(Embedding(4, 3.0f * ExpectedWeight))); + + // Test basic block embedding (should be sum of instruction embeddings) + auto MBBVector = Embedder->getMBBVector(*MBB); + + // Expected BB vector: NOOP + RET + TRAP = [1+2+3, 1+2+3, 1+2+3, 1+2+3] * + // weight = [6, 6, 6, 6] * weight + Embedding ExpectedMBBVector(4, 6.0f * ExpectedWeight); + EXPECT_TRUE(MBBVector.approximatelyEquals(ExpectedMBBVector)); + + // Test function embedding (should equal MBB embedding since we have one MBB) + auto MFuncVector = Embedder->getMFunctionVector(); + EXPECT_TRUE(MFuncVector.approximatelyEquals(ExpectedMBBVector)); +} + +// Test embedder with multiple basic blocks +TEST_F(MIR2VecEmbeddingTestFixture, MultipleBasicBlocks) { + // Create a test vocabulary + auto VocabOrErr = + createTestVocab({{"NOOP", 1.0f}, {"TRAP", 2.0f}}, {}, {}, {}); + ASSERT_TRUE(static_cast<bool>(VocabOrErr)) + << "Failed to create vocabulary: " << toString(VocabOrErr.takeError()); + auto &Vocab = *VocabOrErr; + + // Create two basic blocks using fixture's MF + MachineBasicBlock *MBB1 = MF->CreateMachineBasicBlock(); + MachineBasicBlock *MBB2 = MF->CreateMachineBasicBlock(); + MF->push_back(MBB1); + MF->push_back(MBB2); + + createMachineInstrs(*MBB1, {"NOOP", "NOOP"}); + createMachineInstr(*MBB2, "TRAP"); + + // Create embedder + auto Embedder = SymbolicMIREmbedder::create(*MF, Vocab); + ASSERT_TRUE(Embedder != nullptr); + + // Test basic block embeddings + auto MBB1Vector = Embedder->getMBBVector(*MBB1); + auto MBB2Vector = Embedder->getMBBVector(*MBB2); + + float ExpectedWeight = mir2vec::OpcWeight; + // BB1: NOOP + NOOP = 2 * ([1, 1] * weight) + Embedding ExpectedMBB1Vector(2, 2.0f * ExpectedWeight); + EXPECT_TRUE(MBB1Vector.approximatelyEquals(ExpectedMBB1Vector)); + + // BB2: TRAP = [2, 2] * weight + Embedding ExpectedMBB2Vector(2, 2.0f * ExpectedWeight); + EXPECT_TRUE(MBB2Vector.approximatelyEquals(ExpectedMBB2Vector)); + + // Function embedding: BB1 + BB2 = [2+2, 2+2] * weight = [4, 4] * weight + // Function embedding should be just the first BB embedding as the second BB + // is unreachable + auto MFuncVector = Embedder->getMFunctionVector(); + EXPECT_TRUE(MFuncVector.approximatelyEquals(ExpectedMBB1Vector)); + + // Add a branch from BB1 to BB2 to make both reachable; now function embedding + // should be MBB1 + MBB2 + MBB1->addSuccessor(MBB2); + auto NewMFuncVector = Embedder->getMFunctionVector(); // Recompute embeddings + Embedding ExpectedFuncVector = MBB1Vector + MBB2Vector; + EXPECT_TRUE(NewMFuncVector.approximatelyEquals(ExpectedFuncVector)); +} + +// Test embedder with empty basic block +TEST_F(MIR2VecEmbeddingTestFixture, EmptyBasicBlock) { + + // Create an empty basic block + MachineBasicBlock *MBB = MF->CreateMachineBasicBlock(); + MF->push_back(MBB); + + // Create embedder + auto VocabOrErr = + MIRVocabulary::createDummyVocabForTest(*TII, *TRI, MF->getRegInfo(), 2); + ASSERT_TRUE(static_cast<bool>(VocabOrErr)) + << "Failed to create vocabulary: " << toString(VocabOrErr.takeError()); + auto &V = *VocabOrErr; + auto Embedder = SymbolicMIREmbedder::create(*MF, V); + ASSERT_TRUE(Embedder != nullptr); + + // Test that empty BB has zero embedding + auto MBBVector = Embedder->getMBBVector(*MBB); + Embedding ExpectedBBVector(2, 0.0f); + EXPECT_TRUE(MBBVector.approximatelyEquals(ExpectedBBVector)); + + // Function embedding should also be zero + auto MFuncVector = Embedder->getMFunctionVector(); + EXPECT_TRUE(MFuncVector.approximatelyEquals(ExpectedBBVector)); +} + +// Test embedder with opcodes not in vocabulary +TEST_F(MIR2VecEmbeddingTestFixture, UnknownOpcodes) { + // Create a test vocabulary with limited entries + // SUB is intentionally not included + auto VocabOrErr = createTestVocab({{"ADD", 1.0f}}, {}, {}, {}); + ASSERT_TRUE(static_cast<bool>(VocabOrErr)) + << "Failed to create vocabulary: " << toString(VocabOrErr.takeError()); + auto &Vocab = *VocabOrErr; + + // Create a basic block + MachineBasicBlock *MBB = MF->CreateMachineBasicBlock(); + MF->push_back(MBB); + + // Find opcodes + int AddOpcode = findOpcodeByName("ADD32rr"); + int SubOpcode = findOpcodeByName("SUB32rr"); + + ASSERT_NE(AddOpcode, -1) << "ADD32rr opcode not found"; + ASSERT_NE(SubOpcode, -1) << "SUB32rr opcode not found"; + + // Create instructions + MachineInstr *AddInstr = createMachineInstr(*MBB, AddOpcode); + MachineInstr *SubInstr = createMachineInstr(*MBB, SubOpcode); + + // Create embedder + auto Embedder = SymbolicMIREmbedder::create(*MF, Vocab); + ASSERT_TRUE(Embedder != nullptr); + + // Test instruction embeddings + auto AddVector = Embedder->getMInstVector(*AddInstr); + auto SubVector = Embedder->getMInstVector(*SubInstr); + + float ExpectedWeight = mir2vec::OpcWeight; + // ADD should have the embedding from vocabulary + EXPECT_TRUE( + AddVector.approximatelyEquals(Embedding(2, 1.0f * ExpectedWeight))); + + // SUB should have zero embedding (not in vocabulary) + EXPECT_TRUE(SubVector.approximatelyEquals(Embedding(2, 0.0f))); + + // Basic block embedding should be ADD + SUB = [1.0, 1.0] * weight + [0.0, + // 0.0] = [1.0, 1.0] * weight + const auto &MBBVector = Embedder->getMBBVector(*MBB); + Embedding ExpectedBBVector(2, 1.0f * ExpectedWeight); + EXPECT_TRUE(MBBVector.approximatelyEquals(ExpectedBBVector)); +} + +// Test vocabulary string key generation +TEST_F(MIR2VecEmbeddingTestFixture, VocabularyStringKeys) { + auto VocabOrErr = + createTestVocab({{"ADD", 1.0f}, {"SUB", 2.0f}}, {}, {}, {}, 2); + ASSERT_TRUE(static_cast<bool>(VocabOrErr)) + << "Failed to create vocabulary: " << toString(VocabOrErr.takeError()); + auto &Vocab = *VocabOrErr; + + // Test that we can get string keys for all positions + for (size_t Pos = 0; Pos < Vocab.getCanonicalSize(); ++Pos) { + std::string Key = Vocab.getStringKey(Pos); + EXPECT_FALSE(Key.empty()) << "Empty key at position " << Pos; + } + + // Test specific known positions if we can identify them + unsigned AddIndex = Vocab.getCanonicalIndexForBaseName("ADD"); + std::string AddKey = Vocab.getStringKey(AddIndex); + EXPECT_EQ(AddKey, "ADD"); + + unsigned SubIndex = Vocab.getCanonicalIndexForBaseName("SUB"); + std::string SubKey = Vocab.getStringKey(SubIndex); + EXPECT_EQ(SubKey, "SUB"); + + unsigned ImmIndex = Vocab.getCanonicalIndexForOperandName("Immediate"); + std::string ImmKey = Vocab.getStringKey(ImmIndex); + EXPECT_EQ(ImmKey, "Immediate"); + + unsigned PhyRegIndex = Vocab.getCanonicalIndexForRegisterClass("GR32", true); + std::string PhyRegKey = Vocab.getStringKey(PhyRegIndex); + EXPECT_EQ(PhyRegKey, "PhyReg_GR32"); + + unsigned VirtRegIndex = + Vocab.getCanonicalIndexForRegisterClass("GR32", false); + std::string VirtRegKey = Vocab.getStringKey(VirtRegIndex); + EXPECT_EQ(VirtRegKey, "VirtReg_GR32"); +} + +// Test vocabulary dimension consistency +TEST_F(MIR2VecEmbeddingTestFixture, DimensionConsistency) { + auto VocabOrErr = createTestVocab({{"TEST", 1.0f}}, {}, {}, {}, 5); + ASSERT_TRUE(static_cast<bool>(VocabOrErr)) + << "Failed to create vocabulary: " << toString(VocabOrErr.takeError()); + auto &Vocab = *VocabOrErr; + + EXPECT_EQ(Vocab.getDimension(), 5u); + + // All embeddings should have the same dimension + for (auto IT = Vocab.begin(); IT != Vocab.end(); ++IT) + EXPECT_EQ((*IT).size(), 5u); +} + +// Test invalid register handling through machine instruction creation +TEST_F(MIR2VecEmbeddingTestFixture, InvalidRegisterHandling) { + float MOVValue = 1.5f; + float ImmValue = 0.5f; + float PhyRegValue = 0.2f; + auto VocabOrErr = createTestVocab( + {{"MOV", MOVValue}}, {{"Immediate", ImmValue}}, + {{"GR8_ABCD_H", PhyRegValue}, {"GR8_ABCD_L", PhyRegValue + 0.1f}}, {}, 3); + ASSERT_TRUE(static_cast<bool>(VocabOrErr)) + << "Failed to create vocabulary: " << toString(VocabOrErr.takeError()); + auto &Vocab = *VocabOrErr; + + MachineBasicBlock *MBB = MF->CreateMachineBasicBlock(); + MF->push_back(MBB); + + // Create a MOV instruction with actual operands including potential $noreg + // This tests the actual scenario where invalid registers are encountered + auto MovOpcode = findOpcodeByName("MOV32mr"); + ASSERT_NE(MovOpcode, -1) << "MOV32mr opcode not found"; + const MCInstrDesc &Desc = TII->get(MovOpcode); + + // Use available physical registers from the target + unsigned BaseReg = + TRI->getNumRegs() > 1 ? 1 : 0; // First available physical register + unsigned ValueReg = TRI->getNumRegs() > 2 ? 2 : BaseReg; + + // MOV32mr typically has: base, scale, index, displacement, segment, value + // Use the MachineInstrBuilder API properly + auto MovInst = BuildMI(*MBB, MBB->end(), DebugLoc(), Desc) + .addReg(BaseReg) // base + .addImm(1) // scale + .addReg(0) // index ($noreg) + .addImm(-4) // displacement + .addReg(0) // segment ($noreg) + .addReg(ValueReg); // value + + auto Embedder = SymbolicMIREmbedder::create(*MF, Vocab); + ASSERT_TRUE(Embedder != nullptr); + + // This should not crash even if the instruction has $noreg operands + auto InstEmb = Embedder->getMInstVector(*MovInst); + EXPECT_EQ(InstEmb.size(), 3u); + + // Test the expected embedding value + Embedding ExpectedOpcodeContribution(3, MOVValue * mir2vec::OpcWeight); + auto ExpectedOperandContribution = + Embedding(3, PhyRegValue * mir2vec::RegOperandWeight) // Base + + Embedding(3, ImmValue * mir2vec::CommonOperandWeight) // Scale + + Embedding(3, 0.0f) // noreg + + Embedding(3, ImmValue * mir2vec::CommonOperandWeight) // displacement + + Embedding(3, 0.0f) // noreg + + Embedding(3, (PhyRegValue + 0.1f) * mir2vec::RegOperandWeight); // Value + auto ExpectedEmb = ExpectedOpcodeContribution + ExpectedOperandContribution; + EXPECT_TRUE(InstEmb.approximatelyEquals(ExpectedEmb)) + << "MOV instruction embedding should match expected embedding"; +} + +// Test handling of both physical and virtual registers in an instruction +TEST_F(MIR2VecEmbeddingTestFixture, PhysicalAndVirtualRegisterHandling) { + float MOVValue = 2.0f; + float ImmValue = 0.7f; + float PhyRegValue = 0.3f; + float VirtRegValue = 0.9f; + + // Find GR32 register class + const TargetRegisterClass *GR32RC = nullptr; + for (unsigned i = 0; i < TRI->getNumRegClasses(); ++i) { + const TargetRegisterClass *RC = TRI->getRegClass(i); + if (std::string(TRI->getRegClassName(RC)) == "GR32") { + GR32RC = RC; + break; + } } + ASSERT_TRUE(GR32RC != nullptr && GR32RC->isAllocatable()) + << "No allocatable GR32 register class found"; + + // Get first available physical register from GR32 + unsigned PhyReg = *GR32RC->begin(); + // Create a virtual register of class GR32 + unsigned VirtReg = MF->getRegInfo().createVirtualRegister(GR32RC); + + // Create vocabulary with register class based keys + auto VocabOrErr = + createTestVocab({{"MOV", MOVValue}}, {{"Immediate", ImmValue}}, + {{"GR32_AD", PhyRegValue}}, // GR32_AD is the minimal key + {{"GR32", VirtRegValue}}, 4); + ASSERT_TRUE(static_cast<bool>(VocabOrErr)) + << "Failed to create vocabulary: " << toString(VocabOrErr.takeError()); + auto &Vocab = *VocabOrErr; + + MachineBasicBlock *MBB = MF->CreateMachineBasicBlock(); + MF->push_back(MBB); + + // Create a MOV32rr instruction: MOV32rr dst, src + auto MovOpcode = findOpcodeByName("MOV32rr"); + ASSERT_NE(MovOpcode, -1) << "MOV32rr opcode not found"; + const MCInstrDesc &Desc = TII->get(MovOpcode); + + // MOV32rr: dst (physical), src (virtual) + auto MovInst = BuildMI(*MBB, MBB->end(), DebugLoc(), Desc) + .addReg(PhyReg) // physical register destination + .addReg(VirtReg); // virtual register source + + // Create embedder with virtual register support + auto Embedder = SymbolicMIREmbedder::create(*MF, Vocab); + ASSERT_TRUE(Embedder != nullptr); + + // This should not crash and should produce a valid embedding + auto InstEmb = Embedder->getMInstVector(*MovInst); + EXPECT_EQ(InstEmb.size(), 4u); + + // Test the expected embedding value + Embedding ExpectedOpcodeContribution(4, MOVValue * mir2vec::OpcWeight); + auto ExpectedOperandContribution = + Embedding(4, PhyRegValue * mir2vec::RegOperandWeight) // dst (physical) + + Embedding(4, VirtRegValue * mir2vec::RegOperandWeight); // src (virtual) + auto ExpectedEmb = ExpectedOpcodeContribution + ExpectedOperandContribution; + EXPECT_TRUE(InstEmb.approximatelyEquals(ExpectedEmb)) + << "MOV32rr instruction embedding should match expected embedding"; } +// Test precise embedding calculation with known operands +TEST_F(MIR2VecEmbeddingTestFixture, EmbeddingCalculation) { + auto VocabOrErr = createTestVocab({{"NOOP", 2.0f}}, {}, {}, {}, 2); + ASSERT_TRUE(static_cast<bool>(VocabOrErr)) + << "Failed to create vocabulary: " << toString(VocabOrErr.takeError()); + auto &Vocab = *VocabOrErr; + + MachineBasicBlock *MBB = MF->CreateMachineBasicBlock(); + MF->push_back(MBB); + + // Create a simple NOOP instruction (no operands) + auto NoopInst = createMachineInstr(*MBB, "NOOP"); + ASSERT_TRUE(NoopInst != nullptr); + + auto Embedder = SymbolicMIREmbedder::create(*MF, Vocab); + ASSERT_TRUE(Embedder != nullptr); + + // Get the instruction embedding + auto InstEmb = Embedder->getMInstVector(*NoopInst); + EXPECT_EQ(InstEmb.size(), 2u); + + // For NOOP with no operands, the embedding should be exactly the opcode + // embedding + float ExpectedWeight = mir2vec::OpcWeight; + Embedding ExpectedEmb(2, 2.0f * ExpectedWeight); + + EXPECT_TRUE(InstEmb.approximatelyEquals(ExpectedEmb)) + << "NOOP instruction embedding should match opcode embedding"; + + // Verify individual components + EXPECT_FLOAT_EQ(InstEmb[0], 2.0f * ExpectedWeight); + EXPECT_FLOAT_EQ(InstEmb[1], 2.0f * ExpectedWeight); +} } // namespace diff --git a/llvm/unittests/CodeGen/SelectionDAGPatternMatchTest.cpp b/llvm/unittests/CodeGen/SelectionDAGPatternMatchTest.cpp index 16b9979..aa56aaf 100644 --- a/llvm/unittests/CodeGen/SelectionDAGPatternMatchTest.cpp +++ b/llvm/unittests/CodeGen/SelectionDAGPatternMatchTest.cpp @@ -550,6 +550,31 @@ TEST_F(SelectionDAGPatternMatchTest, matchNode) { EXPECT_FALSE(sd_match(Add, m_Node(ISD::ADD, m_ConstInt(), m_Value()))); } +TEST_F(SelectionDAGPatternMatchTest, matchSelectLike) { + SDLoc DL; + auto Int32VT = EVT::getIntegerVT(Context, 32); + auto VInt32VT = EVT::getVectorVT(Context, Int32VT, 4); + + SDValue Cond = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 0, Int32VT); + SDValue TVal = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, Int32VT); + SDValue FVal = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 2, Int32VT); + + SDValue VCond = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 0, VInt32VT); + SDValue VTVal = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, VInt32VT); + SDValue VFVal = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 2, VInt32VT); + + SDValue Select = DAG->getNode(ISD::SELECT, DL, Int32VT, Cond, TVal, FVal); + SDValue VSelect = + DAG->getNode(ISD::VSELECT, DL, Int32VT, VCond, VTVal, VFVal); + + using namespace SDPatternMatch; + EXPECT_TRUE(sd_match(Select, m_SelectLike(m_Specific(Cond), m_Specific(TVal), + m_Specific(FVal)))); + EXPECT_TRUE( + sd_match(VSelect, m_SelectLike(m_Specific(VCond), m_Specific(VTVal), + m_Specific(VFVal)))); +} + namespace { struct VPMatchContext : public SDPatternMatch::BasicMatchContext { using SDPatternMatch::BasicMatchContext::BasicMatchContext; diff --git a/llvm/unittests/ExecutionEngine/JITLink/JITLinkTestUtils.h b/llvm/unittests/ExecutionEngine/JITLink/JITLinkTestUtils.h index dc077f9..f03c82f 100644 --- a/llvm/unittests/ExecutionEngine/JITLink/JITLinkTestUtils.h +++ b/llvm/unittests/ExecutionEngine/JITLink/JITLinkTestUtils.h @@ -132,7 +132,7 @@ public: : JITLinkContext(&JD), MJMM(std::move(MJMM)), HandleFailed(std::move(HandleFailed)) {} - ~MockJITLinkContext() { + ~MockJITLinkContext() override { if (auto Err = MJMM->deallocate(std::move(FinalizedAllocs))) notifyFailed(std::move(Err)); } diff --git a/llvm/unittests/ExecutionEngine/Orc/EPCGenericMemoryAccessTest.cpp b/llvm/unittests/ExecutionEngine/Orc/EPCGenericMemoryAccessTest.cpp index 2bcff33..a72dc5f 100644 --- a/llvm/unittests/ExecutionEngine/Orc/EPCGenericMemoryAccessTest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/EPCGenericMemoryAccessTest.cpp @@ -140,7 +140,7 @@ public: MemAccess = std::make_unique<EPCGenericMemoryAccess>(*EPC, FAs); } - ~EPCGenericMemoryAccessTest() { cantFail(EPC->disconnect()); } + ~EPCGenericMemoryAccessTest() override { cantFail(EPC->disconnect()); } protected: std::shared_ptr<SelfExecutorProcessControl> EPC; diff --git a/llvm/unittests/ExecutionEngine/Orc/JITLinkRedirectionManagerTest.cpp b/llvm/unittests/ExecutionEngine/Orc/JITLinkRedirectionManagerTest.cpp index a57241b..018a678 100644 --- a/llvm/unittests/ExecutionEngine/Orc/JITLinkRedirectionManagerTest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/JITLinkRedirectionManagerTest.cpp @@ -18,7 +18,7 @@ static int finalTarget() { return 53; } class JITLinkRedirectionManagerTest : public testing::Test { public: - ~JITLinkRedirectionManagerTest() { + ~JITLinkRedirectionManagerTest() override { if (ES) if (auto Err = ES->endSession()) ES->reportError(std::move(Err)); diff --git a/llvm/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp b/llvm/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp index 5ff3e26..5deebec9 100644 --- a/llvm/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp @@ -34,7 +34,7 @@ ArrayRef<char> BlockContent(BlockContentBytes); class ObjectLinkingLayerTest : public testing::Test { public: - ~ObjectLinkingLayerTest() { + ~ObjectLinkingLayerTest() override { if (auto Err = ES.endSession()) ES.reportError(std::move(Err)); } @@ -161,7 +161,7 @@ TEST_F(ObjectLinkingLayerTest, HandleErrorDuringPostAllocationPass) { // abandon the in-flight allocation and report an error. class TestPlugin : public ObjectLinkingLayer::Plugin { public: - ~TestPlugin() { EXPECT_TRUE(ErrorReported); } + ~TestPlugin() override { EXPECT_TRUE(ErrorReported); } void modifyPassConfig(MaterializationResponsibility &MR, jitlink::LinkGraph &G, @@ -215,7 +215,7 @@ TEST_F(ObjectLinkingLayerTest, AddAndRemovePlugins) { TestPlugin(size_t &ActivationCount, bool &PluginDestroyed) : ActivationCount(ActivationCount), PluginDestroyed(PluginDestroyed) {} - ~TestPlugin() { PluginDestroyed = true; } + ~TestPlugin() override { PluginDestroyed = true; } void modifyPassConfig(MaterializationResponsibility &MR, jitlink::LinkGraph &G, @@ -336,7 +336,7 @@ TEST(ObjectLinkingLayerSearchGeneratorTest, AbsoluteSymbolsObjectLayer) { class CheckDefs : public ObjectLinkingLayer::Plugin { public: - ~CheckDefs() { EXPECT_TRUE(SawSymbolDef); } + ~CheckDefs() override { EXPECT_TRUE(SawSymbolDef); } void modifyPassConfig(MaterializationResponsibility &MR, jitlink::LinkGraph &G, diff --git a/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.h b/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.h index 469de2a..e22c35f 100644 --- a/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.h +++ b/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.h @@ -47,7 +47,7 @@ namespace orc { // (5) V -- A JITDylib associated with ES. class CoreAPIsBasedStandardTest : public testing::Test { public: - ~CoreAPIsBasedStandardTest() { + ~CoreAPIsBasedStandardTest() override { if (auto Err = ES.endSession()) ES.reportError(std::move(Err)); } diff --git a/llvm/unittests/ExecutionEngine/Orc/ReOptimizeLayerTest.cpp b/llvm/unittests/ExecutionEngine/Orc/ReOptimizeLayerTest.cpp index 686d85d..ac591c1 100644 --- a/llvm/unittests/ExecutionEngine/Orc/ReOptimizeLayerTest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/ReOptimizeLayerTest.cpp @@ -26,7 +26,7 @@ using namespace llvm::jitlink; class ReOptimizeLayerTest : public testing::Test { public: - ~ReOptimizeLayerTest() { + ~ReOptimizeLayerTest() override { if (ES) if (auto Err = ES->endSession()) ES->reportError(std::move(Err)); diff --git a/llvm/unittests/ExecutionEngine/Orc/ResourceTrackerTest.cpp b/llvm/unittests/ExecutionEngine/Orc/ResourceTrackerTest.cpp index 0e5d1517..3591829b 100644 --- a/llvm/unittests/ExecutionEngine/Orc/ResourceTrackerTest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/ResourceTrackerTest.cpp @@ -50,7 +50,7 @@ public: SimpleResourceManager(SimpleResourceManager &&) = delete; SimpleResourceManager &operator=(SimpleResourceManager &&) = delete; - ~SimpleResourceManager() { ES.deregisterResourceManager(*this); } + ~SimpleResourceManager() override { ES.deregisterResourceManager(*this); } /// Set the HandleRemove function object. void setHandleRemove(HandleRemoveFunction HandleRemove) { diff --git a/llvm/unittests/ExecutionEngine/Orc/WaitingOnGraphTest.cpp b/llvm/unittests/ExecutionEngine/Orc/WaitingOnGraphTest.cpp index b988a78a..08b4e8f 100644 --- a/llvm/unittests/ExecutionEngine/Orc/WaitingOnGraphTest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/WaitingOnGraphTest.cpp @@ -54,7 +54,9 @@ protected: return ContainerElementsMap(); ContainerElementsMap Result = SNs[0]->defs(); +#ifndef NDEBUG const ContainerElementsMap &Deps = SNs[0]->deps(); +#endif // NDEBUG for (size_t I = 1; I != SNs.size(); ++I) { assert(!DepsMustMatch || SNs[I]->deps() == Deps); diff --git a/llvm/unittests/IR/ModuleTest.cpp b/llvm/unittests/IR/ModuleTest.cpp index 36c35673..30eda73 100644 --- a/llvm/unittests/IR/ModuleTest.cpp +++ b/llvm/unittests/IR/ModuleTest.cpp @@ -103,6 +103,36 @@ TEST(ModuleTest, setModuleFlagInt) { EXPECT_EQ(Val2, A2->getZExtValue()); } +TEST(ModuleTest, setModuleFlagTwoMod) { + LLVMContext Context; + Module MA("MA", Context); + Module MB("MB", Context); + StringRef Key = "Key"; + uint32_t Val1 = 1; + uint32_t Val2 = 2; + + // Set a flag to MA + EXPECT_EQ(nullptr, MA.getModuleFlag(Key)); + MA.setModuleFlag(Module::ModFlagBehavior::Error, Key, Val1); + auto A1 = mdconst::extract_or_null<ConstantInt>(MA.getModuleFlag(Key)); + EXPECT_EQ(Val1, A1->getZExtValue()); + + // Set a flag to MB + EXPECT_EQ(nullptr, MB.getModuleFlag(Key)); + MB.setModuleFlag(Module::ModFlagBehavior::Error, Key, Val1); + auto B1 = mdconst::extract_or_null<ConstantInt>(MB.getModuleFlag(Key)); + EXPECT_EQ(Val1, B1->getZExtValue()); + + // Change the flag of MA + MA.setModuleFlag(Module::ModFlagBehavior::Error, Key, Val2); + auto A2 = mdconst::extract_or_null<ConstantInt>(MA.getModuleFlag(Key)); + EXPECT_EQ(Val2, A2->getZExtValue()); + + // MB should keep the original flag value + auto B2 = mdconst::extract_or_null<ConstantInt>(MB.getModuleFlag(Key)); + EXPECT_EQ(Val1, B2->getZExtValue()); +} + const char *IRString = R"IR( !llvm.module.flags = !{!0} diff --git a/llvm/unittests/Support/GlobPatternTest.cpp b/llvm/unittests/Support/GlobPatternTest.cpp index 58fd767..872a21e 100644 --- a/llvm/unittests/Support/GlobPatternTest.cpp +++ b/llvm/unittests/Support/GlobPatternTest.cpp @@ -329,6 +329,72 @@ TEST_F(GlobPatternTest, PrefixSuffix) { EXPECT_EQ("cd", Pat->suffix()); } +TEST_F(GlobPatternTest, Substr) { + auto Pat = GlobPattern::create(""); + ASSERT_TRUE((bool)Pat); + EXPECT_EQ("", Pat->longest_substr()); + + Pat = GlobPattern::create("abcd"); + ASSERT_TRUE((bool)Pat); + EXPECT_EQ("", Pat->longest_substr()); + + Pat = GlobPattern::create("a*bcd"); + ASSERT_TRUE((bool)Pat); + EXPECT_EQ("", Pat->longest_substr()); + + Pat = GlobPattern::create("*abcd"); + ASSERT_TRUE((bool)Pat); + EXPECT_EQ("", Pat->longest_substr()); + + Pat = GlobPattern::create("abcd*"); + ASSERT_TRUE((bool)Pat); + EXPECT_EQ("", Pat->longest_substr()); + + Pat = GlobPattern::create("a*bc*d"); + ASSERT_TRUE((bool)Pat); + EXPECT_EQ("bc", Pat->longest_substr()); + + Pat = GlobPattern::create("a*bc*def*g"); + ASSERT_TRUE((bool)Pat); + EXPECT_EQ("def", Pat->longest_substr()); + + Pat = GlobPattern::create("a*bcd*ef*g"); + ASSERT_TRUE((bool)Pat); + EXPECT_EQ("bcd", Pat->longest_substr()); + + Pat = GlobPattern::create("a*bcd*efg*h"); + ASSERT_TRUE((bool)Pat); + EXPECT_EQ("bcd", Pat->longest_substr()); + + Pat = GlobPattern::create("a*bcd[ef]g*h"); + ASSERT_TRUE((bool)Pat); + EXPECT_EQ("bcd", Pat->longest_substr()); + + Pat = GlobPattern::create("a*bc[d]efg*h"); + ASSERT_TRUE((bool)Pat); + EXPECT_EQ("efg", Pat->longest_substr()); + + Pat = GlobPattern::create("a*bc[]]efg*h"); + ASSERT_TRUE((bool)Pat); + EXPECT_EQ("efg", Pat->longest_substr()); + + Pat = GlobPattern::create("a*bcde\\fg*h"); + ASSERT_TRUE((bool)Pat); + EXPECT_EQ("bcde", Pat->longest_substr()); + + Pat = GlobPattern::create("a*bcde\\[fg*h"); + ASSERT_TRUE((bool)Pat); + EXPECT_EQ("bcde", Pat->longest_substr()); + + Pat = GlobPattern::create("a*bcde?fg*h"); + ASSERT_TRUE((bool)Pat); + EXPECT_EQ("bcde", Pat->longest_substr()); + + Pat = GlobPattern::create("a*bcdef{g}*h"); + ASSERT_TRUE((bool)Pat); + EXPECT_EQ("bcdef", Pat->longest_substr()); +} + TEST_F(GlobPatternTest, Pathological) { std::string P, S(40, 'a'); StringRef Pieces[] = {"a*", "[ba]*", "{b*,a*}*"}; diff --git a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp index 5d69a31..bfc1275 100644 --- a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp +++ b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp @@ -730,6 +730,11 @@ TEST(ParseArchString, MissingDepency) { EXPECT_EQ(toString(RISCVISAInfo::parseArchString(Input, true).takeError()), ""); } + + EXPECT_EQ(toString(RISCVISAInfo::parseArchString("rv64i_xsfvfbfexp16e", true) + .takeError()), + "'xsfvfbfexp16e' requires 'zvfbfmin' or 'zvfbfa' extension to also " + "be specified"); } TEST(ParseArchString, RejectsUnrecognizedProfileNames) { @@ -1162,6 +1167,11 @@ R"(All available -march extensions for RISC-V xsfmm64t 0.6 xsfmmbase 0.6 xsfvcp 1.0 + xsfvfbfexp16e 0.5 + xsfvfexp16e 0.5 + xsfvfexp32e 0.5 + xsfvfexpa 0.2 + xsfvfexpa64e 0.2 xsfvfnrclipxfqf 1.0 xsfvfwmaccqqq 1.0 xsfvqmaccdod 1.0 diff --git a/llvm/unittests/TargetParser/TargetParserTest.cpp b/llvm/unittests/TargetParser/TargetParserTest.cpp index 53a64b6..ef6aeae 100644 --- a/llvm/unittests/TargetParser/TargetParserTest.cpp +++ b/llvm/unittests/TargetParser/TargetParserTest.cpp @@ -47,6 +47,7 @@ const char *ARMArch[] = { "armv9-a", "armv9", "armv9a", "armv9.1-a", "armv9.1a", "armv9.2-a", "armv9.2a", "armv9.3-a", "armv9.3a", "armv9.4-a", "armv9.4a", "armv9.5-a", "armv9.5a", "armv9.6a", "armv9.6-a", + "armv9.7a", "armv9.7-a", }; std::string FormatExtensionFlags(int64_t Flags) { @@ -622,6 +623,8 @@ TEST(TargetParserTest, testARMArch) { ARMBuildAttrs::CPUArch::v9_A)); EXPECT_TRUE(testARMArch("armv9.6-a", "generic", "v9.6a", ARMBuildAttrs::CPUArch::v9_A)); + EXPECT_TRUE(testARMArch("armv9.7-a", "generic", "v9.7a", + ARMBuildAttrs::CPUArch::v9_A)); EXPECT_TRUE( testARMArch("armv8-r", "generic", "v8r", ARMBuildAttrs::CPUArch::v8_R)); EXPECT_TRUE(testARMArch("armv8-m.base", "generic", "v8m.base", @@ -937,6 +940,7 @@ TEST(TargetParserTest, ARMparseArchProfile) { case ARM::ArchKind::ARMV9_4A: case ARM::ArchKind::ARMV9_5A: case ARM::ArchKind::ARMV9_6A: + case ARM::ArchKind::ARMV9_7A: EXPECT_EQ(ARM::ProfileKind::A, ARM::parseArchProfile(ARMArch[i])); break; default: @@ -1294,6 +1298,7 @@ TEST(TargetParserTest, testAArch64Arch) { EXPECT_TRUE(testAArch64Arch("armv9.4-a")); EXPECT_TRUE(testAArch64Arch("armv9.5-a")); EXPECT_TRUE(testAArch64Arch("armv9.6-a")); + EXPECT_TRUE(testAArch64Arch("armv9.7-a")); } bool testAArch64Extension(StringRef CPUName, StringRef ArchExt) { @@ -1438,7 +1443,13 @@ TEST(TargetParserTest, AArch64ExtensionFeatures) { AArch64::AEK_SVEAES, AArch64::AEK_SME_MOP4, AArch64::AEK_SME_TMOP, AArch64::AEK_SVEBITPERM, AArch64::AEK_SSVE_BITPERM, AArch64::AEK_SVESHA3, - AArch64::AEK_SVESM4, + AArch64::AEK_SVESM4, AArch64::AEK_CMH, + AArch64::AEK_LSCP, AArch64::AEK_TLBID, + AArch64::AEK_MPAMV2, AArch64::AEK_MTETC, + AArch64::AEK_GCIE, AArch64::AEK_SME2P3, + AArch64::AEK_SVE2P3, AArch64::AEK_SVE_B16MM, + AArch64::AEK_F16MM, AArch64::AEK_F16F32DOT, + AArch64::AEK_F16F32MM, }; std::vector<StringRef> Features; @@ -1550,6 +1561,18 @@ TEST(TargetParserTest, AArch64ExtensionFeatures) { EXPECT_TRUE(llvm::is_contained(Features, "+pops")); EXPECT_TRUE(llvm::is_contained(Features, "+sme-mop4")); EXPECT_TRUE(llvm::is_contained(Features, "+sme-tmop")); + EXPECT_TRUE(llvm::is_contained(Features, "+cmh")); + EXPECT_TRUE(llvm::is_contained(Features, "+lscp")); + EXPECT_TRUE(llvm::is_contained(Features, "+tlbid")); + EXPECT_TRUE(llvm::is_contained(Features, "+mpamv2")); + EXPECT_TRUE(llvm::is_contained(Features, "+mtetc")); + EXPECT_TRUE(llvm::is_contained(Features, "+gcie")); + EXPECT_TRUE(llvm::is_contained(Features, "+sme2p3")); + EXPECT_TRUE(llvm::is_contained(Features, "+sve2p3")); + EXPECT_TRUE(llvm::is_contained(Features, "+sve-b16mm")); + EXPECT_TRUE(llvm::is_contained(Features, "+f16mm")); + EXPECT_TRUE(llvm::is_contained(Features, "+f16f32dot")); + EXPECT_TRUE(llvm::is_contained(Features, "+f16f32mm")); // Assuming we listed every extension above, this should produce the same // result. @@ -1576,6 +1599,7 @@ TEST(TargetParserTest, AArch64ArchFeatures) { EXPECT_EQ(AArch64::ARMV9_4A.ArchFeature, "+v9.4a"); EXPECT_EQ(AArch64::ARMV9_5A.ArchFeature, "+v9.5a"); EXPECT_EQ(AArch64::ARMV9_6A.ArchFeature, "+v9.6a"); + EXPECT_EQ(AArch64::ARMV9_7A.ArchFeature, "+v9.7a"); EXPECT_EQ(AArch64::ARMV8R.ArchFeature, "+v8r"); } @@ -1605,7 +1629,8 @@ TEST(TargetParserTest, AArch64ArchPartialOrder) { for (const auto *A : {&AArch64::ARMV9_1A, &AArch64::ARMV9_2A, &AArch64::ARMV9_3A, - &AArch64::ARMV9_4A, &AArch64::ARMV9_5A, &AArch64::ARMV9_6A}) + &AArch64::ARMV9_4A, &AArch64::ARMV9_5A, &AArch64::ARMV9_6A, + &AArch64::ARMV9_7A}) EXPECT_TRUE(A->implies(AArch64::ARMV9A)); EXPECT_TRUE(AArch64::ARMV8_1A.implies(AArch64::ARMV8A)); @@ -1624,6 +1649,7 @@ TEST(TargetParserTest, AArch64ArchPartialOrder) { EXPECT_TRUE(AArch64::ARMV9_4A.implies(AArch64::ARMV9_3A)); EXPECT_TRUE(AArch64::ARMV9_5A.implies(AArch64::ARMV9_4A)); EXPECT_TRUE(AArch64::ARMV9_6A.implies(AArch64::ARMV9_5A)); + EXPECT_TRUE(AArch64::ARMV9_7A.implies(AArch64::ARMV9_6A)); EXPECT_TRUE(AArch64::ARMV9A.implies(AArch64::ARMV8_5A)); EXPECT_TRUE(AArch64::ARMV9_1A.implies(AArch64::ARMV8_6A)); @@ -1713,6 +1739,18 @@ TEST(TargetParserTest, AArch64ArchExtFeature) { {"pops", "nopops", "+pops", "-pops"}, {"sme-mop4", "nosme-mop4", "+sme-mop4", "-sme-mop4"}, {"sme-tmop", "nosme-tmop", "+sme-tmop", "-sme-tmop"}, + {"cmh", "nocmh", "+cmh", "-cmh"}, + {"lscp", "nolscp", "+lscp", "-lscp"}, + {"tlbid", "notlbid", "+tlbid", "-tlbid"}, + {"mpamv2", "nompamv2", "+mpamv2", "-mpamv2"}, + {"mtetc", "nomtetc", "+mtetc", "-mtetc"}, + {"gcie", "nogcie", "+gcie", "-gcie"}, + {"sme2p3", "nosme2p3", "+sme2p3", "-sme2p3"}, + {"sve2p3", "nosve2p3", "+sve2p3", "-sve2p3"}, + {"sve-b16mm", "nosve-b16mm", "+sve-b16mm", "-sve-b16mm"}, + {"f16mm", "nof16mm", "+f16mm", "-f16mm"}, + {"f16f32dot", "nof16f32dot", "+f16f32dot", "-f16f32dot"}, + {"f16f32mm", "nof16f32mm", "+f16f32mm", "-f16f32mm"}, }; for (unsigned i = 0; i < std::size(ArchExt); i++) { @@ -1927,7 +1965,8 @@ AArch64ExtensionDependenciesBaseArchTestParams {AArch64::ARMV9_6A, {"nofp", "fprcvt"}, {"fp-armv8", "fprcvt"}, {}}, {AArch64::ARMV9_6A, {"fprcvt", "nofp"}, {}, {"fp-armv8", "fprcvt"}}, - // simd -> {aes, sha2, sha3, sm4, f8f16mm, f8f32mm, faminmax, lut, fp8} + // simd -> {aes, sha2, sha3, sm4, f8f16mm, f8f32mm, faminmax, lut, fp8, + // f16f32dot, f16f32mm} {AArch64::ARMV8A, {"nosimd", "aes"}, {"neon", "aes"}, {}}, {AArch64::ARMV8A, {"aes", "nosimd"}, {}, {"neon", "aes"}}, {AArch64::ARMV8A, {"nosimd", "sha2"}, {"neon", "sha2"}, {}}, @@ -1946,6 +1985,10 @@ AArch64ExtensionDependenciesBaseArchTestParams {AArch64::ARMV9_6A, {"nosimd", "lut"}, {"neon", "lut"}, {}}, {AArch64::ARMV9_6A, {"fp8", "nosimd"}, {}, {"neon", "fp8"}}, {AArch64::ARMV9_6A, {"nosimd", "fp8"}, {"neon", "fp8"}, {}}, + {AArch64::ARMV9_7A, {"nosimd", "f16f32mm"}, {"neon", "f16f32mm"}, {}}, + {AArch64::ARMV9_7A, {"f16f32mm", "nosimd"}, {}, {"neon", "f16f32mm"}}, + {AArch64::ARMV9_7A, {"nosimd", "f16f32dot"}, {"neon", "f16f32dot"}, {}}, + {AArch64::ARMV9_7A, {"f16f32dot", "nosimd"}, {}, {"neon", "f16f32dot"}}, // fp8 -> {fp8dot4, fp8dot2} {AArch64::ARMV9_6A, {"nofp8", "fp8dot4"}, {"fp8", "fp8dot4"}, {}}, @@ -1961,17 +2004,35 @@ AArch64ExtensionDependenciesBaseArchTestParams {AArch64::ARMV8A, {"nosimd", "fcma"}, {"neon", "complxnum"}, {}}, {AArch64::ARMV8A, {"fcma", "nosimd"}, {}, {"neon", "complxnum"}}, - // fp16 -> {fp16fml, sve} + // fp16 -> {fp16fml, sve, f16f32dot, f16f32mm, f16mm} {AArch64::ARMV8A, {"nofp16", "fp16fml"}, {"fullfp16", "fp16fml"}, {}}, {AArch64::ARMV8A, {"fp16fml", "nofp16"}, {}, {"fullfp16", "fp16fml"}}, {AArch64::ARMV8A, {"nofp16", "sve"}, {"fullfp16", "sve"}, {}}, {AArch64::ARMV8A, {"sve", "nofp16"}, {}, {"fullfp16", "sve"}}, + {AArch64::ARMV9_7A, {"nofp16", "f16mm"}, {"fullfp16", "f16mm"}, {}}, + {AArch64::ARMV9_7A, {"f16mm", "nofp16"}, {}, {"fullfp16", "f16mm"}}, + {AArch64::ARMV9_7A, + {"nofp16", "f16f32mm"}, + {"fullfp16", "f16f32mm"}, + {}}, + {AArch64::ARMV9_7A, + {"f16f32mm", "nofp16"}, + {}, + {"fullfp16", "f16f32mm"}}, + {AArch64::ARMV9_7A, + {"nofp16", "f16f32dot"}, + {"fullfp16", "f16f32dot"}, + {}}, + {AArch64::ARMV9_7A, + {"f16f32dot", "nofp16"}, + {}, + {"fullfp16", "f16f32dot"}}, // bf16 -> {sme} {AArch64::ARMV8A, {"nobf16", "sme"}, {"bf16", "sme"}, {}}, {AArch64::ARMV8A, {"sme", "nobf16"}, {}, {"bf16", "sme"}}, - // sve -> {sve2, f32mm, f64mm, sve-f16f32mm} + // sve -> {sve2, f32mm, f64mm, sve-f16f32mm, sve-b16mm} {AArch64::ARMV8A, {"nosve", "sve2"}, {"sve", "sve2"}, {}}, {AArch64::ARMV8A, {"sve2", "nosve"}, {}, {"sve", "sve2"}}, {AArch64::ARMV8A, {"nosve", "f32mm"}, {"sve", "f32mm"}, {}}, @@ -1986,6 +2047,8 @@ AArch64ExtensionDependenciesBaseArchTestParams {"sve-f16f32mm", "nosve"}, {}, {"sve", "sve-f16f32mm"}}, + {AArch64::ARMV9_7A, {"nosve", "sve-b16mm"}, {"sve", "sve-b16mm"}, {}}, + {AArch64::ARMV9_7A, {"sve-b16mm", "nosve"}, {}, {"sve", "sve-b16mm"}}, // aes -> {sve-aes} {AArch64::ARMV8A, {"noaes", "sve-aes"}, {"aes", "sve-aes"}, {}}, @@ -2031,6 +2094,10 @@ AArch64ExtensionDependenciesBaseArchTestParams {AArch64::ARMV9_6A, {"nosve2p1", "sve2p2"}, {"sve2p1", "sve2p2"}, {}}, {AArch64::ARMV9_6A, {"sve2p2", "nosve2p1"}, {}, {"sve2p1", "sve2p2"}}, + // sve2p2 -> {sve2p3} + {AArch64::ARMV9_7A, {"nosve2p2", "sve2p3"}, {"sve2p2", "sve2p3"}, {}}, + {AArch64::ARMV9_7A, {"sve2p3", "nosve2p2"}, {}, {"sve2p2", "sve2p3"}}, + // sme -> {sme2, sme-f16f16, sme-f64f64, sme-i16i64, sme-fa64} {AArch64::ARMV8A, {"nosme", "sme2"}, {"sme", "sme2"}, {}}, {AArch64::ARMV8A, {"sme2", "nosme"}, {}, {"sme", "sme2"}}, @@ -2084,6 +2151,10 @@ AArch64ExtensionDependenciesBaseArchTestParams {AArch64::ARMV9_6A, {"nosme2p1", "sme2p2"}, {"sme2p2", "sme2p1"}, {}}, {AArch64::ARMV9_6A, {"sme2p2", "nosme2p1"}, {}, {"sme2p1", "sme2p2"}}, + // sme2p2 -> {sme2p3} + {AArch64::ARMV9_7A, {"nosme2p2", "sme2p3"}, {"sme2p3", "sme2p2"}, {}}, + {AArch64::ARMV9_7A, {"sme2p3", "nosme2p2"}, {}, {"sme2p2", "sme2p3"}}, + // fp8 -> {sme-f8f16, sme-f8f32, f8f16mm, f8f32mm, fp8dot4, fp8dot2, // ssve-fp8dot4, ssve-fp8dot2} {AArch64::ARMV8A, {"nofp8", "sme-f8f16"}, {"fp8", "sme-f8f16"}, {}}, diff --git a/llvm/unittests/Transforms/Utils/BasicBlockUtilsTest.cpp b/llvm/unittests/Transforms/Utils/BasicBlockUtilsTest.cpp index 3c9374b..4235c93 100644 --- a/llvm/unittests/Transforms/Utils/BasicBlockUtilsTest.cpp +++ b/llvm/unittests/Transforms/Utils/BasicBlockUtilsTest.cpp @@ -716,3 +716,32 @@ attributes #0 = { presplitcoroutine } EXPECT_FALSE(llvm::isPresplitCoroSuspendExitEdge( *ExitN.getSinglePredecessor(), ExitN)); } + +TEST(BasicBlockUtils, BasicBlockPrintable) { + std::string S; + std::string SCheck; + llvm::raw_string_ostream OS{S}; + llvm::raw_string_ostream OSCheck{SCheck}; + + LLVMContext C; + std::unique_ptr<Module> M = parseIR(C, R"IR( +define void @foo() { + br label %bb0 +bb0: + br label %.exit +.exit: + ret void +} +)IR"); + + Function *F = M->getFunction("foo"); + for (const BasicBlock &BB : *F) { + OS << printBasicBlock(&BB); + BB.printAsOperand(OSCheck); + EXPECT_EQ(OS.str(), OSCheck.str()); + S.clear(); + SCheck.clear(); + } + OS << printBasicBlock(nullptr); + EXPECT_EQ(OS.str(), "<nullptr>"); +} diff --git a/llvm/unittests/Transforms/Vectorize/VPDomTreeTest.cpp b/llvm/unittests/Transforms/Vectorize/VPDomTreeTest.cpp index 2a0f500..e108c4d 100644 --- a/llvm/unittests/Transforms/Vectorize/VPDomTreeTest.cpp +++ b/llvm/unittests/Transforms/Vectorize/VPDomTreeTest.cpp @@ -33,7 +33,7 @@ TEST_F(VPDominatorTreeTest, DominanceNoRegionsTest) { VPBasicBlock *VPBB2 = Plan.createVPBasicBlock("VPBB2"); VPBasicBlock *VPBB3 = Plan.createVPBasicBlock("VPBB3"); VPBasicBlock *VPBB4 = Plan.createVPBasicBlock("VPBB4"); - VPRegionBlock *R1 = Plan.createVPRegionBlock(VPBB1, VPBB4); + VPRegionBlock *R1 = Plan.createLoopRegion("R1", VPBB1, VPBB4); VPBB2->setParent(R1); VPBB3->setParent(R1); @@ -99,7 +99,7 @@ TEST_F(VPDominatorTreeTest, DominanceRegionsTest) { VPBasicBlock *R1BB2 = Plan.createVPBasicBlock(""); VPBasicBlock *R1BB3 = Plan.createVPBasicBlock(""); VPBasicBlock *R1BB4 = Plan.createVPBasicBlock(""); - VPRegionBlock *R1 = Plan.createVPRegionBlock(R1BB1, R1BB4, "R1"); + VPRegionBlock *R1 = Plan.createLoopRegion("R1", R1BB1, R1BB4); R1BB2->setParent(R1); R1BB3->setParent(R1); VPBlockUtils::connectBlocks(VPBB0, R1); @@ -112,7 +112,7 @@ TEST_F(VPDominatorTreeTest, DominanceRegionsTest) { VPBasicBlock *R2BB1 = Plan.createVPBasicBlock(""); VPBasicBlock *R2BB2 = Plan.createVPBasicBlock(""); - VPRegionBlock *R2 = Plan.createVPRegionBlock(R2BB1, R2BB2, "R2"); + VPRegionBlock *R2 = Plan.createLoopRegion("R2", R2BB1, R2BB2); VPBlockUtils::connectBlocks(R2BB1, R2BB2); VPBlockUtils::connectBlocks(R1, R2); @@ -171,12 +171,12 @@ TEST_F(VPDominatorTreeTest, DominanceRegionsTest) { VPBasicBlock *R1BB1 = Plan.createVPBasicBlock("R1BB1"); VPBasicBlock *R1BB2 = Plan.createVPBasicBlock("R1BB2"); VPBasicBlock *R1BB3 = Plan.createVPBasicBlock("R1BB3"); - VPRegionBlock *R1 = Plan.createVPRegionBlock(R1BB1, R1BB3, "R1"); + VPRegionBlock *R1 = Plan.createLoopRegion("R1", R1BB1, R1BB3); VPBasicBlock *R2BB1 = Plan.createVPBasicBlock("R2BB1"); VPBasicBlock *R2BB2 = Plan.createVPBasicBlock("R2BB2"); VPBasicBlock *R2BB3 = Plan.createVPBasicBlock("R2BB#"); - VPRegionBlock *R2 = Plan.createVPRegionBlock(R2BB1, R2BB3, "R2"); + VPRegionBlock *R2 = Plan.createLoopRegion("R2", R2BB1, R2BB3); R2BB2->setParent(R2); VPBlockUtils::connectBlocks(R2BB1, R2BB2); VPBlockUtils::connectBlocks(R2BB2, R2BB1); diff --git a/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp b/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp index db64c75..c1791dfa 100644 --- a/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp +++ b/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp @@ -269,7 +269,7 @@ TEST_F(VPBasicBlockTest, getPlan) { // VPBasicBlock is the entry into the VPlan, followed by a region. VPBasicBlock *R1BB1 = Plan.createVPBasicBlock(""); VPBasicBlock *R1BB2 = Plan.createVPBasicBlock(""); - VPRegionBlock *R1 = Plan.createVPRegionBlock(R1BB1, R1BB2, "R1"); + VPRegionBlock *R1 = Plan.createLoopRegion("R1", R1BB1, R1BB2); VPBlockUtils::connectBlocks(R1BB1, R1BB2); VPBlockUtils::connectBlocks(VPBB1, R1); @@ -286,12 +286,12 @@ TEST_F(VPBasicBlockTest, getPlan) { VPlan &Plan = getPlan(); VPBasicBlock *R1BB1 = Plan.createVPBasicBlock(""); VPBasicBlock *R1BB2 = Plan.createVPBasicBlock(""); - VPRegionBlock *R1 = Plan.createVPRegionBlock(R1BB1, R1BB2, "R1"); + VPRegionBlock *R1 = Plan.createLoopRegion("R1", R1BB1, R1BB2); VPBlockUtils::connectBlocks(R1BB1, R1BB2); VPBasicBlock *R2BB1 = Plan.createVPBasicBlock(""); VPBasicBlock *R2BB2 = Plan.createVPBasicBlock(""); - VPRegionBlock *R2 = Plan.createVPRegionBlock(R2BB1, R2BB2, "R2"); + VPRegionBlock *R2 = Plan.createLoopRegion("R2", R2BB1, R2BB2); VPBlockUtils::connectBlocks(R2BB1, R2BB2); VPBasicBlock *VPBB1 = Plan.getEntry(); @@ -369,7 +369,7 @@ TEST_F(VPBasicBlockTest, TraversingIteratorTest) { VPBasicBlock *R1BB2 = Plan.createVPBasicBlock(""); VPBasicBlock *R1BB3 = Plan.createVPBasicBlock(""); VPBasicBlock *R1BB4 = Plan.createVPBasicBlock(""); - VPRegionBlock *R1 = Plan.createVPRegionBlock(R1BB1, R1BB4, "R1"); + VPRegionBlock *R1 = Plan.createLoopRegion("R1", R1BB1, R1BB4); R1BB2->setParent(R1); R1BB3->setParent(R1); VPBlockUtils::connectBlocks(VPBB0, R1); @@ -382,7 +382,7 @@ TEST_F(VPBasicBlockTest, TraversingIteratorTest) { VPBasicBlock *R2BB1 = Plan.createVPBasicBlock(""); VPBasicBlock *R2BB2 = Plan.createVPBasicBlock(""); - VPRegionBlock *R2 = Plan.createVPRegionBlock(R2BB1, R2BB2, "R2"); + VPRegionBlock *R2 = Plan.createLoopRegion("R2", R2BB1, R2BB2); VPBlockUtils::connectBlocks(R2BB1, R2BB2); VPBlockUtils::connectBlocks(R1, R2); @@ -467,12 +467,12 @@ TEST_F(VPBasicBlockTest, TraversingIteratorTest) { VPBasicBlock *R1BB1 = Plan.createVPBasicBlock("R1BB1"); VPBasicBlock *R1BB2 = Plan.createVPBasicBlock("R1BB2"); VPBasicBlock *R1BB3 = Plan.createVPBasicBlock("R1BB3"); - VPRegionBlock *R1 = Plan.createVPRegionBlock(R1BB1, R1BB3, "R1"); + VPRegionBlock *R1 = Plan.createLoopRegion("R1", R1BB1, R1BB3); VPBasicBlock *R2BB1 = Plan.createVPBasicBlock("R2BB1"); VPBasicBlock *R2BB2 = Plan.createVPBasicBlock("R2BB2"); VPBasicBlock *R2BB3 = Plan.createVPBasicBlock("R2BB3"); - VPRegionBlock *R2 = Plan.createVPRegionBlock(R2BB1, R2BB3, "R2"); + VPRegionBlock *R2 = Plan.createLoopRegion("R2", R2BB1, R2BB3); R2BB2->setParent(R2); VPBlockUtils::connectBlocks(R2BB1, R2BB2); VPBlockUtils::connectBlocks(R2BB2, R2BB1); @@ -537,10 +537,10 @@ TEST_F(VPBasicBlockTest, TraversingIteratorTest) { VPlan &Plan = getPlan(); VPBasicBlock *R2BB1 = Plan.createVPBasicBlock("R2BB1"); VPBasicBlock *R2BB2 = Plan.createVPBasicBlock("R2BB2"); - VPRegionBlock *R2 = Plan.createVPRegionBlock(R2BB1, R2BB2, "R2"); + VPRegionBlock *R2 = Plan.createLoopRegion("R2", R2BB1, R2BB2); VPBlockUtils::connectBlocks(R2BB1, R2BB2); - VPRegionBlock *R1 = Plan.createVPRegionBlock(R2, R2, "R1"); + VPRegionBlock *R1 = Plan.createLoopRegion("R1", R2, R2); R2->setParent(R1); VPBasicBlock *VPBB1 = Plan.getEntry(); @@ -590,14 +590,14 @@ TEST_F(VPBasicBlockTest, TraversingIteratorTest) { // VPlan &Plan = getPlan(); VPBasicBlock *R3BB1 = Plan.createVPBasicBlock("R3BB1"); - VPRegionBlock *R3 = Plan.createVPRegionBlock(R3BB1, R3BB1, "R3"); + VPRegionBlock *R3 = Plan.createLoopRegion("R3", R3BB1, R3BB1); VPBasicBlock *R2BB1 = Plan.createVPBasicBlock("R2BB1"); - VPRegionBlock *R2 = Plan.createVPRegionBlock(R2BB1, R3, "R2"); + VPRegionBlock *R2 = Plan.createLoopRegion("R2", R2BB1, R3); R3->setParent(R2); VPBlockUtils::connectBlocks(R2BB1, R3); - VPRegionBlock *R1 = Plan.createVPRegionBlock(R2, R2, "R1"); + VPRegionBlock *R1 = Plan.createLoopRegion("R1", R2, R2); R2->setParent(R1); VPBasicBlock *VPBB1 = Plan.getEntry(); @@ -687,7 +687,7 @@ TEST_F(VPBasicBlockTest, reassociateBlocks) { VPlan &Plan = getPlan(); VPBasicBlock *VPBB1 = Plan.createVPBasicBlock("VPBB1"); VPBasicBlock *VPBB2 = Plan.createVPBasicBlock("VPBB2"); - VPRegionBlock *R1 = Plan.createVPRegionBlock(VPBB2, VPBB2, "R1"); + VPRegionBlock *R1 = Plan.createLoopRegion("R1", VPBB2, VPBB2); VPBlockUtils::connectBlocks(VPBB1, R1); auto *WidenPhi = new VPWidenPHIRecipe(nullptr); diff --git a/llvm/unittests/Transforms/Vectorize/VPlanVerifierTest.cpp b/llvm/unittests/Transforms/Vectorize/VPlanVerifierTest.cpp index c2f045b..50ad4d5 100644 --- a/llvm/unittests/Transforms/Vectorize/VPlanVerifierTest.cpp +++ b/llvm/unittests/Transforms/Vectorize/VPlanVerifierTest.cpp @@ -32,7 +32,7 @@ TEST_F(VPVerifierTest, VPInstructionUseBeforeDefSameBB) { VPBasicBlock *VPBB2 = Plan.createVPBasicBlock(""); VPBB2->appendRecipe(CanIV); - VPRegionBlock *R1 = Plan.createVPRegionBlock(VPBB2, VPBB2, "R1"); + VPRegionBlock *R1 = Plan.createLoopRegion("R1", VPBB2, VPBB2); VPBlockUtils::connectBlocks(VPBB1, R1); VPBlockUtils::connectBlocks(R1, Plan.getScalarHeader()); @@ -71,7 +71,7 @@ TEST_F(VPVerifierTest, VPInstructionUseBeforeDefDifferentBB) { VPBB2->appendRecipe(DefI); VPBB2->appendRecipe(BranchOnCond); - VPRegionBlock *R1 = Plan.createVPRegionBlock(VPBB2, VPBB2, "R1"); + VPRegionBlock *R1 = Plan.createLoopRegion("R1", VPBB2, VPBB2); VPBlockUtils::connectBlocks(VPBB1, R1); VPBlockUtils::connectBlocks(R1, Plan.getScalarHeader()); @@ -117,7 +117,7 @@ TEST_F(VPVerifierTest, VPBlendUseBeforeDefDifferentBB) { VPBlockUtils::connectBlocks(VPBB2, VPBB3); VPBlockUtils::connectBlocks(VPBB3, VPBB4); - VPRegionBlock *R1 = Plan.createVPRegionBlock(VPBB2, VPBB4, "R1"); + VPRegionBlock *R1 = Plan.createLoopRegion("R1", VPBB2, VPBB4); VPBlockUtils::connectBlocks(VPBB1, R1); VPBB3->setParent(R1); @@ -160,7 +160,7 @@ TEST_F(VPVerifierTest, VPPhiIncomingValueDoesntDominateIncomingBlock) { auto *CanIV = new VPCanonicalIVPHIRecipe(Zero, {}); VPBB3->appendRecipe(CanIV); - VPRegionBlock *R1 = Plan.createVPRegionBlock(VPBB3, VPBB3, "R1"); + VPRegionBlock *R1 = Plan.createLoopRegion("R1", VPBB3, VPBB3); VPBlockUtils::connectBlocks(VPBB1, VPBB2); VPBlockUtils::connectBlocks(VPBB2, R1); VPBlockUtils::connectBlocks(VPBB4, Plan.getScalarHeader()); @@ -200,7 +200,7 @@ TEST_F(VPVerifierTest, DuplicateSuccessorsOutsideRegion) { VPBB2->appendRecipe(CanIV); VPBB2->appendRecipe(BranchOnCond); - VPRegionBlock *R1 = Plan.createVPRegionBlock(VPBB2, VPBB2, "R1"); + VPRegionBlock *R1 = Plan.createLoopRegion("R1", VPBB2, VPBB2); VPBlockUtils::connectBlocks(VPBB1, R1); VPBlockUtils::connectBlocks(VPBB1, R1); @@ -237,7 +237,7 @@ TEST_F(VPVerifierTest, DuplicateSuccessorsInsideRegion) { VPBlockUtils::connectBlocks(VPBB2, VPBB3); VPBlockUtils::connectBlocks(VPBB2, VPBB3); - VPRegionBlock *R1 = Plan.createVPRegionBlock(VPBB2, VPBB3, "R1"); + VPRegionBlock *R1 = Plan.createLoopRegion("R1", VPBB2, VPBB3); VPBlockUtils::connectBlocks(VPBB1, R1); VPBB3->setParent(R1); @@ -270,7 +270,7 @@ TEST_F(VPVerifierTest, BlockOutsideRegionWithParent) { VPBB1->appendRecipe(DefI); VPBB2->appendRecipe(BranchOnCond); - VPRegionBlock *R1 = Plan.createVPRegionBlock(VPBB2, VPBB2, "R1"); + VPRegionBlock *R1 = Plan.createLoopRegion("R1", VPBB2, VPBB2); VPBlockUtils::connectBlocks(VPBB1, R1); VPBlockUtils::connectBlocks(R1, Plan.getScalarHeader()); @@ -302,7 +302,7 @@ TEST_F(VPVerifierTest, NonHeaderPHIInHeader) { VPBB2->appendRecipe(IRPhi); VPBB2->appendRecipe(BranchOnCond); - VPRegionBlock *R1 = Plan.createVPRegionBlock(VPBB2, VPBB2, "R1"); + VPRegionBlock *R1 = Plan.createLoopRegion("R1", VPBB2, VPBB2); VPBlockUtils::connectBlocks(VPBB1, R1); VPBlockUtils::connectBlocks(R1, Plan.getScalarHeader()); |
