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