1fa99cb64SMircea Trofin //===- MachineInstrTest.cpp -----------------------------------------------===// 2fa99cb64SMircea Trofin // 3fa99cb64SMircea Trofin // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4fa99cb64SMircea Trofin // See https://llvm.org/LICENSE.txt for license information. 5fa99cb64SMircea Trofin // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6fa99cb64SMircea Trofin // 7fa99cb64SMircea Trofin //===----------------------------------------------------------------------===// 8fa99cb64SMircea Trofin 9fa99cb64SMircea Trofin #include "../lib/CodeGen/RegAllocScore.h" 10*bb3f5e1fSMatin Raayai #include "llvm/CodeGen/CodeGenTargetMachineImpl.h" 11fa99cb64SMircea Trofin #include "llvm/CodeGen/MachineBasicBlock.h" 12fa99cb64SMircea Trofin #include "llvm/CodeGen/MachineFunction.h" 13fa99cb64SMircea Trofin #include "llvm/CodeGen/MachineInstr.h" 14fa99cb64SMircea Trofin #include "llvm/CodeGen/MachineMemOperand.h" 15fa99cb64SMircea Trofin #include "llvm/CodeGen/MachineModuleInfo.h" 16fa99cb64SMircea Trofin #include "llvm/CodeGen/TargetFrameLowering.h" 17fa99cb64SMircea Trofin #include "llvm/CodeGen/TargetInstrInfo.h" 18fa99cb64SMircea Trofin #include "llvm/CodeGen/TargetLowering.h" 19fa99cb64SMircea Trofin #include "llvm/CodeGen/TargetSubtargetInfo.h" 20fa99cb64SMircea Trofin #include "llvm/IR/DebugInfoMetadata.h" 21fa99cb64SMircea Trofin #include "llvm/IR/IRBuilder.h" 2274deadf1SNikita Popov #include "llvm/IR/Module.h" 23fa99cb64SMircea Trofin #include "llvm/IR/ModuleSlotTracker.h" 24fa99cb64SMircea Trofin #include "llvm/MC/MCAsmInfo.h" 25fa99cb64SMircea Trofin #include "llvm/MC/MCSymbol.h" 26fa99cb64SMircea Trofin #include "llvm/MC/TargetRegistry.h" 27fa99cb64SMircea Trofin #include "llvm/Support/TargetSelect.h" 28fa99cb64SMircea Trofin #include "llvm/Target/TargetOptions.h" 2962c7f035SArchibald Elliott #include "llvm/TargetParser/Triple.h" 30fa99cb64SMircea Trofin #include "gtest/gtest.h" 31fa99cb64SMircea Trofin 32fa99cb64SMircea Trofin using namespace llvm; 33fa99cb64SMircea Trofin extern cl::opt<double> CopyWeight; 34fa99cb64SMircea Trofin extern cl::opt<double> LoadWeight; 35fa99cb64SMircea Trofin extern cl::opt<double> StoreWeight; 36fa99cb64SMircea Trofin extern cl::opt<double> CheapRematWeight; 37fa99cb64SMircea Trofin extern cl::opt<double> ExpensiveRematWeight; 38fa99cb64SMircea Trofin 39fa99cb64SMircea Trofin namespace { 40fa99cb64SMircea Trofin // Include helper functions to ease the manipulation of MachineFunctions. 41fa99cb64SMircea Trofin #include "MFCommon.inc" 42fa99cb64SMircea Trofin 43fa99cb64SMircea Trofin // MachineFunction::CreateMachineInstr doesn't copy the MCInstrDesc, it 44fa99cb64SMircea Trofin // takes its address. So we want a bunch of pre-allocated mock MCInstrDescs. 45fa99cb64SMircea Trofin #define MOCK_INSTR(MACRO) \ 46fa99cb64SMircea Trofin MACRO(Copy, TargetOpcode::COPY, 0) \ 47fa99cb64SMircea Trofin MACRO(Load, 0, 1ULL << MCID::MayLoad) \ 48fa99cb64SMircea Trofin MACRO(Store, 0, 1ULL << MCID::MayStore) \ 49fa99cb64SMircea Trofin MACRO(LoadStore, 0, (1ULL << MCID::MayLoad) | (1ULL << MCID::MayStore)) \ 50fa99cb64SMircea Trofin MACRO(CheapRemat, 0, 1ULL << MCID::CheapAsAMove) \ 51fa99cb64SMircea Trofin MACRO(ExpensiveRemat, 0, 0) \ 52fa99cb64SMircea Trofin MACRO(Dbg, TargetOpcode::DBG_LABEL, \ 53fa99cb64SMircea Trofin (1ULL << MCID::MayLoad) | (1ULL << MCID::MayStore)) \ 54fa99cb64SMircea Trofin MACRO(InlAsm, TargetOpcode::INLINEASM, \ 55fa99cb64SMircea Trofin (1ULL << MCID::MayLoad) | (1ULL << MCID::MayStore)) \ 56fa99cb64SMircea Trofin MACRO(Kill, TargetOpcode::KILL, \ 57fa99cb64SMircea Trofin (1ULL << MCID::MayLoad) | (1ULL << MCID::MayStore)) 58fa99cb64SMircea Trofin 59fa99cb64SMircea Trofin enum MockInstrId { 60fa99cb64SMircea Trofin #define MOCK_INSTR_ID(ID, IGNORE, IGNORE2) ID, 61fa99cb64SMircea Trofin MOCK_INSTR(MOCK_INSTR_ID) 62fa99cb64SMircea Trofin #undef MOCK_INSTR_ID 63fa99cb64SMircea Trofin TotalMockInstrs 64fa99cb64SMircea Trofin }; 65fa99cb64SMircea Trofin 66fa99cb64SMircea Trofin const std::array<MCInstrDesc, MockInstrId::TotalMockInstrs> MockInstrDescs{{ 67fa99cb64SMircea Trofin #define MOCK_SPEC(IGNORE, OPCODE, FLAGS) \ 688dcdc37aSJay Foad {OPCODE, 0, 0, 0, 0, 0, 0, 0, 0, FLAGS, 0}, 69fa99cb64SMircea Trofin MOCK_INSTR(MOCK_SPEC) 70fa99cb64SMircea Trofin #undef MOCK_SPEC 71fa99cb64SMircea Trofin }}; 72fa99cb64SMircea Trofin 73fa99cb64SMircea Trofin MachineInstr *createMockCopy(MachineFunction &MF) { 74fa99cb64SMircea Trofin return MF.CreateMachineInstr(MockInstrDescs[MockInstrId::Copy], DebugLoc()); 75fa99cb64SMircea Trofin } 76fa99cb64SMircea Trofin 77fa99cb64SMircea Trofin MachineInstr *createMockLoad(MachineFunction &MF) { 78fa99cb64SMircea Trofin return MF.CreateMachineInstr(MockInstrDescs[MockInstrId::Load], DebugLoc()); 79fa99cb64SMircea Trofin } 80fa99cb64SMircea Trofin 81fa99cb64SMircea Trofin MachineInstr *createMockStore(MachineFunction &MF) { 82fa99cb64SMircea Trofin return MF.CreateMachineInstr(MockInstrDescs[MockInstrId::Store], DebugLoc()); 83fa99cb64SMircea Trofin } 84fa99cb64SMircea Trofin 85fa99cb64SMircea Trofin MachineInstr *createMockLoadStore(MachineFunction &MF) { 86fa99cb64SMircea Trofin return MF.CreateMachineInstr(MockInstrDescs[MockInstrId::LoadStore], 87fa99cb64SMircea Trofin DebugLoc()); 88fa99cb64SMircea Trofin } 89fa99cb64SMircea Trofin 90fa99cb64SMircea Trofin MachineInstr *createMockCheapRemat(MachineFunction &MF) { 91fa99cb64SMircea Trofin return MF.CreateMachineInstr(MockInstrDescs[MockInstrId::CheapRemat], 92fa99cb64SMircea Trofin DebugLoc()); 93fa99cb64SMircea Trofin } 94fa99cb64SMircea Trofin 95fa99cb64SMircea Trofin MachineInstr *createMockExpensiveRemat(MachineFunction &MF) { 96fa99cb64SMircea Trofin return MF.CreateMachineInstr(MockInstrDescs[MockInstrId::ExpensiveRemat], 97fa99cb64SMircea Trofin DebugLoc()); 98fa99cb64SMircea Trofin } 99fa99cb64SMircea Trofin 100fa99cb64SMircea Trofin MachineInstr *createMockDebug(MachineFunction &MF) { 101fa99cb64SMircea Trofin return MF.CreateMachineInstr(MockInstrDescs[MockInstrId::Dbg], DebugLoc()); 102fa99cb64SMircea Trofin } 103fa99cb64SMircea Trofin 104fa99cb64SMircea Trofin MachineInstr *createMockKill(MachineFunction &MF) { 105fa99cb64SMircea Trofin return MF.CreateMachineInstr(MockInstrDescs[MockInstrId::Kill], DebugLoc()); 106fa99cb64SMircea Trofin } 107fa99cb64SMircea Trofin 108fa99cb64SMircea Trofin MachineInstr *createMockInlineAsm(MachineFunction &MF) { 109fa99cb64SMircea Trofin return MF.CreateMachineInstr(MockInstrDescs[MockInstrId::InlAsm], DebugLoc()); 110fa99cb64SMircea Trofin } 111fa99cb64SMircea Trofin 112fa99cb64SMircea Trofin TEST(RegAllocScoreTest, SkipDebugKillInlineAsm) { 113fa99cb64SMircea Trofin LLVMContext Ctx; 114fa99cb64SMircea Trofin Module Mod("Module", Ctx); 115fa99cb64SMircea Trofin auto MF = createMachineFunction(Ctx, Mod); 116fa99cb64SMircea Trofin 117fa99cb64SMircea Trofin auto *MBB = MF->CreateMachineBasicBlock(); 118fa99cb64SMircea Trofin MF->insert(MF->end(), MBB); 119fa99cb64SMircea Trofin auto MBBFreqMock = [&](const MachineBasicBlock &_MBB) -> double { 120fa99cb64SMircea Trofin assert(&_MBB == MBB); 121fa99cb64SMircea Trofin return 0.5; 122fa99cb64SMircea Trofin }; 123fa99cb64SMircea Trofin auto Next = MBB->end(); 124fa99cb64SMircea Trofin Next = MBB->insertAfter(Next, createMockInlineAsm(*MF)); 125fa99cb64SMircea Trofin Next = MBB->insertAfter(Next, createMockDebug(*MF)); 126fa99cb64SMircea Trofin Next = MBB->insertAfter(Next, createMockKill(*MF)); 127fa99cb64SMircea Trofin const auto Score = llvm::calculateRegAllocScore( 128fa99cb64SMircea Trofin *MF, MBBFreqMock, [](const MachineInstr &) { return false; }); 129fa99cb64SMircea Trofin ASSERT_EQ(MF->size(), 1U); 130fa99cb64SMircea Trofin ASSERT_EQ(Score, RegAllocScore()); 131fa99cb64SMircea Trofin } 132fa99cb64SMircea Trofin 133fa99cb64SMircea Trofin TEST(RegAllocScoreTest, Counts) { 134fa99cb64SMircea Trofin LLVMContext Ctx; 135fa99cb64SMircea Trofin Module Mod("Module", Ctx); 136fa99cb64SMircea Trofin auto MF = createMachineFunction(Ctx, Mod); 137fa99cb64SMircea Trofin 138fa99cb64SMircea Trofin auto *MBB1 = MF->CreateMachineBasicBlock(); 139fa99cb64SMircea Trofin auto *MBB2 = MF->CreateMachineBasicBlock(); 140fa99cb64SMircea Trofin MF->insert(MF->end(), MBB1); 141fa99cb64SMircea Trofin MF->insert(MF->end(), MBB2); 142fa99cb64SMircea Trofin const double Freq1 = 0.5; 143fa99cb64SMircea Trofin const double Freq2 = 10.0; 144fa99cb64SMircea Trofin auto MBBFreqMock = [&](const MachineBasicBlock &MBB) -> double { 145fa99cb64SMircea Trofin if (&MBB == MBB1) 146fa99cb64SMircea Trofin return Freq1; 147fa99cb64SMircea Trofin if (&MBB == MBB2) 148fa99cb64SMircea Trofin return Freq2; 149fd722c59SSimon Pilgrim llvm_unreachable("We only created 2 basic blocks"); 150fa99cb64SMircea Trofin }; 151fa99cb64SMircea Trofin auto Next = MBB1->end(); 152fa99cb64SMircea Trofin Next = MBB1->insertAfter(Next, createMockCopy(*MF)); 153fa99cb64SMircea Trofin Next = MBB1->insertAfter(Next, createMockLoad(*MF)); 154fa99cb64SMircea Trofin Next = MBB1->insertAfter(Next, createMockLoad(*MF)); 155fa99cb64SMircea Trofin Next = MBB1->insertAfter(Next, createMockStore(*MF)); 156fa99cb64SMircea Trofin auto *CheapRemat = createMockCheapRemat(*MF); 157fa99cb64SMircea Trofin MBB1->insertAfter(Next, CheapRemat); 158fa99cb64SMircea Trofin Next = MBB2->end(); 159fa99cb64SMircea Trofin Next = MBB2->insertAfter(Next, createMockLoad(*MF)); 160fa99cb64SMircea Trofin Next = MBB2->insertAfter(Next, createMockStore(*MF)); 161fa99cb64SMircea Trofin Next = MBB2->insertAfter(Next, createMockLoadStore(*MF)); 162fa99cb64SMircea Trofin auto *ExpensiveRemat = createMockExpensiveRemat(*MF); 163fa99cb64SMircea Trofin MBB2->insertAfter(Next, ExpensiveRemat); 164fa99cb64SMircea Trofin auto IsRemat = [&](const MachineInstr &MI) { 165fa99cb64SMircea Trofin return &MI == CheapRemat || &MI == ExpensiveRemat; 166fa99cb64SMircea Trofin }; 167fa99cb64SMircea Trofin ASSERT_EQ(MF->size(), 2U); 168fa99cb64SMircea Trofin const auto TotalScore = 169fa99cb64SMircea Trofin llvm::calculateRegAllocScore(*MF, MBBFreqMock, IsRemat); 1708cd8ebe1SAiden Grossman ASSERT_DOUBLE_EQ(Freq1, TotalScore.copyCounts()); 1718cd8ebe1SAiden Grossman ASSERT_DOUBLE_EQ(2.0 * Freq1 + Freq2, TotalScore.loadCounts()); 1728cd8ebe1SAiden Grossman ASSERT_DOUBLE_EQ(Freq1 + Freq2, TotalScore.storeCounts()); 1738cd8ebe1SAiden Grossman ASSERT_DOUBLE_EQ(Freq2, TotalScore.loadStoreCounts()); 1748cd8ebe1SAiden Grossman ASSERT_DOUBLE_EQ(Freq1, TotalScore.cheapRematCounts()); 1758cd8ebe1SAiden Grossman ASSERT_DOUBLE_EQ(Freq2, TotalScore.expensiveRematCounts()); 1768cd8ebe1SAiden Grossman ASSERT_DOUBLE_EQ( 1778cd8ebe1SAiden Grossman TotalScore.getScore(), 178fa99cb64SMircea Trofin TotalScore.copyCounts() * CopyWeight + 179fa99cb64SMircea Trofin TotalScore.loadCounts() * LoadWeight + 180fa99cb64SMircea Trofin TotalScore.storeCounts() * StoreWeight + 181fa99cb64SMircea Trofin TotalScore.loadStoreCounts() * (LoadWeight + StoreWeight) + 182fa99cb64SMircea Trofin TotalScore.cheapRematCounts() * CheapRematWeight + 183fa99cb64SMircea Trofin TotalScore.expensiveRematCounts() * ExpensiveRematWeight 184fa99cb64SMircea Trofin 185fa99cb64SMircea Trofin ); 186fa99cb64SMircea Trofin } 187fa99cb64SMircea Trofin } // end namespace 188