#include "llvm/CodeGen/MIRParser/MIRParser.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/TargetFrameLowering.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/IR/DIBuilder.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "../lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.h"
#include "gtest/gtest.h"
using namespace llvm;
using namespace LiveDebugValues;
#include "MFCommon.inc"
class InstrRefLDVTest : public testing::Test {
public:
friend class InstrRefBasedLDV;
using MLocTransferMap = InstrRefBasedLDV::MLocTransferMap;
LLVMContext Ctx;
std::unique_ptr<Module> Mod;
std::unique_ptr<TargetMachine> Machine;
std::unique_ptr<MachineFunction> MF;
std::unique_ptr<MachineDominatorTree> DomTree;
std::unique_ptr<MachineModuleInfo> MMI;
DICompileUnit *OurCU;
DIFile *OurFile;
DISubprogram *OurFunc;
DILexicalBlock *OurBlock, *AnotherBlock;
DISubprogram *ToInlineFunc;
DILexicalBlock *ToInlineBlock;
DILocalVariable *FuncVariable;
DIBasicType *LongInt;
DIExpression *EmptyExpr;
LiveDebugValues::OverlapMap Overlaps;
DebugLoc OutermostLoc, InBlockLoc, NotNestedBlockLoc, InlinedLoc;
MachineBasicBlock *MBB0, *MBB1, *MBB2, *MBB3, *MBB4;
std::unique_ptr<InstrRefBasedLDV> LDV;
std::unique_ptr<MLocTracker> MTracker;
std::unique_ptr<VLocTracker> VTracker;
SmallString<256> MIRStr;
InstrRefLDVTest() : Ctx(), Mod(std::make_unique<Module>("beehives", Ctx)) {}
void SetUp() {
Mod->setDataLayout("e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-"
"n8:16:32:64-S128");
Triple TargetTriple("x86_64--");
std::string Error;
const Target *T = TargetRegistry::lookupTarget("", TargetTriple, Error);
if (!T)
GTEST_SKIP();
TargetOptions Options;
Machine = std::unique_ptr<TargetMachine>(
T->createTargetMachine(Triple::normalize("x86_64--"), "", "", Options,
None, None, CodeGenOpt::Aggressive));
auto Type = FunctionType::get(Type::getVoidTy(Ctx), false);
auto F =
Function::Create(Type, GlobalValue::ExternalLinkage, "Test", &*Mod);
unsigned FunctionNum = 42;
MMI = std::make_unique<MachineModuleInfo>((LLVMTargetMachine *)&*Machine);
const TargetSubtargetInfo &STI = *Machine->getSubtargetImpl(*F);
MF = std::make_unique<MachineFunction>(*F, (LLVMTargetMachine &)*Machine,
STI, FunctionNum, *MMI);
DIBuilder DIB(*Mod);
OurFile = DIB.createFile("xyzzy.c", "/cave");
OurCU =
DIB.createCompileUnit(dwarf::DW_LANG_C99, OurFile, "nou", false, "", 0);
auto OurSubT = DIB.createSubroutineType(DIB.getOrCreateTypeArray(None));
OurFunc =
DIB.createFunction(OurCU, "bees", "", OurFile, 1, OurSubT, 1,
DINode::FlagZero, DISubprogram::SPFlagDefinition);
F->setSubprogram(OurFunc);
OurBlock = DIB.createLexicalBlock(OurFunc, OurFile, 2, 3);
AnotherBlock = DIB.createLexicalBlock(OurFunc, OurFile, 2, 6);
ToInlineFunc =
DIB.createFunction(OurFile, "shoes", "", OurFile, 10, OurSubT, 10,
DINode::FlagZero, DISubprogram::SPFlagDefinition);
OutermostLoc = DILocation::get(Ctx, 3, 1, OurFunc);
InBlockLoc = DILocation::get(Ctx, 4, 1, OurBlock);
InlinedLoc = DILocation::get(Ctx, 10, 1, ToInlineFunc, InBlockLoc.get());
NotNestedBlockLoc = DILocation::get(Ctx, 4, 1, AnotherBlock);
LongInt = DIB.createBasicType("long", 64, llvm::dwarf::DW_ATE_unsigned);
FuncVariable = DIB.createAutoVariable(OurFunc, "lala", OurFile, 1, LongInt);
EmptyExpr = DIExpression::get(Ctx, {});
DIB.finalize();
}
Register getRegByName(const char *WantedName) {
auto *TRI = MF->getRegInfo().getTargetRegisterInfo();
for (unsigned int I = 1; I < TRI->getNumRegs(); ++I) {
const char *Name = TRI->getName(I);
if (strcmp(WantedName, Name) == 0)
return I;
}
llvm_unreachable("Can't find register by name");
}
InstrRefBasedLDV *setupLDVObj(MachineFunction *MF) {
LDV = std::make_unique<InstrRefBasedLDV>();
const TargetSubtargetInfo &STI = MF->getSubtarget();
LDV->TII = STI.getInstrInfo();
LDV->TRI = STI.getRegisterInfo();
LDV->TFI = STI.getFrameLowering();
LDV->MFI = &MF->getFrameInfo();
LDV->MRI = &MF->getRegInfo();
DomTree = std::make_unique<MachineDominatorTree>(*MF);
LDV->DomTree = &*DomTree;
LDV->initialSetup(*MF);
LDV->LS.initialize(*MF);
addMTracker(MF);
return &*LDV;
}
void addMTracker(MachineFunction *MF) {
ASSERT_TRUE(LDV);
const TargetSubtargetInfo &STI = MF->getSubtarget();
MTracker = std::make_unique<MLocTracker>(
*MF, *LDV->TII, *LDV->TRI, *STI.getTargetLowering());
LDV->MTracker = &*MTracker;
}
void addVTracker() {
ASSERT_TRUE(LDV);
VTracker = std::make_unique<VLocTracker>(Overlaps, EmptyExpr);
LDV->VTracker = &*VTracker;
}
void buildMLocValueMap(FuncValueTable &MInLocs, FuncValueTable &MOutLocs,
SmallVectorImpl<MLocTransferMap> &MLocTransfer) {
LDV->buildMLocValueMap(*MF, MInLocs, MOutLocs, MLocTransfer);
}
void placeMLocPHIs(MachineFunction &MF,
SmallPtrSetImpl<MachineBasicBlock *> &AllBlocks,
FuncValueTable &MInLocs,
SmallVectorImpl<MLocTransferMap> &MLocTransfer) {
LDV->placeMLocPHIs(MF, AllBlocks, MInLocs, MLocTransfer);
}
Optional<ValueIDNum>
pickVPHILoc(const MachineBasicBlock &MBB, const DebugVariable &Var,
const InstrRefBasedLDV::LiveIdxT &LiveOuts, FuncValueTable &MOutLocs,
const SmallVectorImpl<const MachineBasicBlock *> &BlockOrders) {
return LDV->pickVPHILoc(MBB, Var, LiveOuts, MOutLocs, BlockOrders);
}
bool vlocJoin(MachineBasicBlock &MBB, InstrRefBasedLDV::LiveIdxT &VLOCOutLocs,
SmallPtrSet<const MachineBasicBlock *, 8> &BlocksToExplore,
DbgValue &InLoc) {
return LDV->vlocJoin(MBB, VLOCOutLocs, BlocksToExplore, InLoc);
}
void buildVLocValueMap(const DILocation *DILoc,
const SmallSet<DebugVariable, 4> &VarsWeCareAbout,
SmallPtrSetImpl<MachineBasicBlock *> &AssignBlocks,
InstrRefBasedLDV::LiveInsT &Output, FuncValueTable &MOutLocs,
FuncValueTable &MInLocs,
SmallVectorImpl<VLocTracker> &AllTheVLocs) {
LDV->buildVLocValueMap(DILoc, VarsWeCareAbout, AssignBlocks, Output,
MOutLocs, MInLocs, AllTheVLocs);
}
void initValueArray(FuncValueTable &Nums, unsigned Blks, unsigned Locs) {
for (unsigned int I = 0; I < Blks; ++I)
for (unsigned int J = 0; J < Locs; ++J)
Nums[I][J] = ValueIDNum::EmptyValue;
}
void setupSingleBlock() {
Function &F = const_cast<llvm::Function &>(MF->getFunction());
auto *BB0 = BasicBlock::Create(Ctx, "entry", &F);
IRBuilder<> IRB(BB0);
IRB.CreateRetVoid();
MBB0 = MF->CreateMachineBasicBlock(BB0);
MF->insert(MF->end(), MBB0);
MF->RenumberBlocks();
setupLDVObj(&*MF);
}
void setupDiamondBlocks() {
llvm::Function &F = const_cast<llvm::Function &>(MF->getFunction());
auto *BB0 = BasicBlock::Create(Ctx, "a", &F);
auto *BB1 = BasicBlock::Create(Ctx, "b", &F);
auto *BB2 = BasicBlock::Create(Ctx, "c", &F);
auto *BB3 = BasicBlock::Create(Ctx, "d", &F);
IRBuilder<> IRB0(BB0), IRB1(BB1), IRB2(BB2), IRB3(BB3);
IRB0.CreateBr(BB1);
IRB1.CreateBr(BB2);
IRB2.CreateBr(BB3);
IRB3.CreateRetVoid();
MBB0 = MF->CreateMachineBasicBlock(BB0);
MF->insert(MF->end(), MBB0);
MBB1 = MF->CreateMachineBasicBlock(BB1);
MF->insert(MF->end(), MBB1);
MBB2 = MF->CreateMachineBasicBlock(BB2);
MF->insert(MF->end(), MBB2);
MBB3 = MF->CreateMachineBasicBlock(BB3);
MF->insert(MF->end(), MBB3);
MBB0->addSuccessor(MBB1);
MBB0->addSuccessor(MBB2);
MBB1->addSuccessor(MBB3);
MBB2->addSuccessor(MBB3);
MF->RenumberBlocks();
setupLDVObj(&*MF);
}
void setupSimpleLoop() {
llvm::Function &F = const_cast<llvm::Function &>(MF->getFunction());
auto *BB0 = BasicBlock::Create(Ctx, "entry", &F);
auto *BB1 = BasicBlock::Create(Ctx, "loop", &F);
auto *BB2 = BasicBlock::Create(Ctx, "ret", &F);
IRBuilder<> IRB0(BB0), IRB1(BB1), IRB2(BB2);
IRB0.CreateBr(BB1);
IRB1.CreateBr(BB2);
IRB2.CreateRetVoid();
MBB0 = MF->CreateMachineBasicBlock(BB0);
MF->insert(MF->end(), MBB0);
MBB1 = MF->CreateMachineBasicBlock(BB1);
MF->insert(MF->end(), MBB1);
MBB2 = MF->CreateMachineBasicBlock(BB2);
MF->insert(MF->end(), MBB2);
MBB0->addSuccessor(MBB1);
MBB1->addSuccessor(MBB2);
MBB1->addSuccessor(MBB1);
MF->RenumberBlocks();
setupLDVObj(&*MF);
}
void setupNestedLoops() {
llvm::Function &F = const_cast<llvm::Function &>(MF->getFunction());
auto *BB0 = BasicBlock::Create(Ctx, "entry", &F);
auto *BB1 = BasicBlock::Create(Ctx, "loop1", &F);
auto *BB2 = BasicBlock::Create(Ctx, "loop2", &F);
auto *BB3 = BasicBlock::Create(Ctx, "join", &F);
auto *BB4 = BasicBlock::Create(Ctx, "ret", &F);
IRBuilder<> IRB0(BB0), IRB1(BB1), IRB2(BB2), IRB3(BB3), IRB4(BB4);
IRB0.CreateBr(BB1);
IRB1.CreateBr(BB2);
IRB2.CreateBr(BB3);
IRB3.CreateBr(BB4);
IRB4.CreateRetVoid();
MBB0 = MF->CreateMachineBasicBlock(BB0);
MF->insert(MF->end(), MBB0);
MBB1 = MF->CreateMachineBasicBlock(BB1);
MF->insert(MF->end(), MBB1);
MBB2 = MF->CreateMachineBasicBlock(BB2);
MF->insert(MF->end(), MBB2);
MBB3 = MF->CreateMachineBasicBlock(BB3);
MF->insert(MF->end(), MBB3);
MBB4 = MF->CreateMachineBasicBlock(BB4);
MF->insert(MF->end(), MBB4);
MBB0->addSuccessor(MBB1);
MBB1->addSuccessor(MBB2);
MBB2->addSuccessor(MBB2);
MBB2->addSuccessor(MBB3);
MBB3->addSuccessor(MBB1);
MBB3->addSuccessor(MBB4);
MF->RenumberBlocks();
setupLDVObj(&*MF);
}
void setupNoDominatingLoop() {
llvm::Function &F = const_cast<llvm::Function &>(MF->getFunction());
auto *BB0 = BasicBlock::Create(Ctx, "entry", &F);
auto *BB1 = BasicBlock::Create(Ctx, "head1", &F);
auto *BB2 = BasicBlock::Create(Ctx, "head2", &F);
auto *BB3 = BasicBlock::Create(Ctx, "joinblk", &F);
auto *BB4 = BasicBlock::Create(Ctx, "ret", &F);
IRBuilder<> IRB0(BB0), IRB1(BB1), IRB2(BB2), IRB3(BB3), IRB4(BB4);
IRB0.CreateBr(BB1);
IRB1.CreateBr(BB2);
IRB2.CreateBr(BB3);
IRB3.CreateBr(BB4);
IRB4.CreateRetVoid();
MBB0 = MF->CreateMachineBasicBlock(BB0);
MF->insert(MF->end(), MBB0);
MBB1 = MF->CreateMachineBasicBlock(BB1);
MF->insert(MF->end(), MBB1);
MBB2 = MF->CreateMachineBasicBlock(BB2);
MF->insert(MF->end(), MBB2);
MBB3 = MF->CreateMachineBasicBlock(BB3);
MF->insert(MF->end(), MBB3);
MBB4 = MF->CreateMachineBasicBlock(BB4);
MF->insert(MF->end(), MBB4);
MBB0->addSuccessor(MBB1);
MBB0->addSuccessor(MBB2);
MBB1->addSuccessor(MBB3);
MBB2->addSuccessor(MBB3);
MBB3->addSuccessor(MBB1);
MBB3->addSuccessor(MBB2);
MBB3->addSuccessor(MBB4);
MF->RenumberBlocks();
setupLDVObj(&*MF);
}
void setupBadlyNestedLoops() {
llvm::Function &F = const_cast<llvm::Function &>(MF->getFunction());
auto *BB0 = BasicBlock::Create(Ctx, "entry", &F);
auto *BB1 = BasicBlock::Create(Ctx, "loop1", &F);
auto *BB2 = BasicBlock::Create(Ctx, "loop2", &F);
auto *BB3 = BasicBlock::Create(Ctx, "loop3", &F);
auto *BB4 = BasicBlock::Create(Ctx, "ret", &F);
IRBuilder<> IRB0(BB0), IRB1(BB1), IRB2(BB2), IRB3(BB3), IRB4(BB4);
IRB0.CreateBr(BB1);
IRB1.CreateBr(BB2);
IRB2.CreateBr(BB3);
IRB3.CreateBr(BB4);
IRB4.CreateRetVoid();
MBB0 = MF->CreateMachineBasicBlock(BB0);
MF->insert(MF->end(), MBB0);
MBB1 = MF->CreateMachineBasicBlock(BB1);
MF->insert(MF->end(), MBB1);
MBB2 = MF->CreateMachineBasicBlock(BB2);
MF->insert(MF->end(), MBB2);
MBB3 = MF->CreateMachineBasicBlock(BB3);
MF->insert(MF->end(), MBB3);
MBB4 = MF->CreateMachineBasicBlock(BB4);
MF->insert(MF->end(), MBB4);
MBB0->addSuccessor(MBB1);
MBB1->addSuccessor(MBB1);
MBB1->addSuccessor(MBB2);
MBB2->addSuccessor(MBB1);
MBB2->addSuccessor(MBB2);
MBB2->addSuccessor(MBB3);
MBB3->addSuccessor(MBB2);
MBB3->addSuccessor(MBB3);
MBB3->addSuccessor(MBB4);
MF->RenumberBlocks();
setupLDVObj(&*MF);
}
MachineFunction *readMIRBlock(const char *Input) {
MIRStr.clear();
StringRef S = Twine(Twine(R"MIR(
--- |
target triple = "x86_64-unknown-linux-gnu"
define void @test() { ret void }
...
---
name: test
tracksRegLiveness: true
stack:
- { id: 0, name: '', type: spill-slot, offset: -16, size: 8, alignment: 8,
stack-id: default, callee-saved-register: '', callee-saved-restored: true,
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
body: |
bb.0:
liveins: $rdi, $rsi
)MIR") + Twine(Input) + Twine("...\n"))
.toNullTerminatedStringRef(MIRStr);
;
if (Function *Fn = Mod->getFunction("test"))
MMI->deleteMachineFunctionFor(*Fn);
auto MemBuf = MemoryBuffer::getMemBuffer(S, "<input>");
auto MIRParse = createMIRParser(std::move(MemBuf), Ctx);
Mod = MIRParse->parseIRModule();
assert(Mod);
Mod->setDataLayout("e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-"
"n8:16:32:64-S128");
bool Result = MIRParse->parseMachineFunctions(*Mod, *MMI);
assert(!Result && "Failed to parse unit test machine function?");
(void)Result;
Function *Fn = Mod->getFunction("test");
assert(Fn && "Failed to parse a unit test module string?");
Fn->setSubprogram(OurFunc);
return MMI->getMachineFunction(*Fn);
}
void
produceMLocTransferFunction(MachineFunction &MF,
SmallVectorImpl<MLocTransferMap> &MLocTransfer,
unsigned MaxNumBlocks) {
LDV->produceMLocTransferFunction(MF, MLocTransfer, MaxNumBlocks);
}
std::pair<FuncValueTable, FuncValueTable>
allocValueTables(unsigned Blocks, unsigned Locs) {
FuncValueTable MOutLocs = std::make_unique<ValueTable[]>(Blocks);
FuncValueTable MInLocs = std::make_unique<ValueTable[]>(Blocks);
for (unsigned int I = 0; I < Blocks; ++I) {
MOutLocs[I] = std::make_unique<ValueIDNum[]>(Locs);
MInLocs[I] = std::make_unique<ValueIDNum[]>(Locs);
}
return std::make_pair(std::move(MOutLocs), std::move(MInLocs));
}
};
TEST_F(InstrRefLDVTest, MTransferDefs) {
MachineFunction *MF = readMIRBlock(
" $rax = MOV64ri 0\n"
" RET64 $rax\n");
setupLDVObj(MF);
EXPECT_TRUE(MTracker->getNumLocs() == 1);
SmallVector<MLocTransferMap, 1> TransferMap;
TransferMap.resize(1);
produceMLocTransferFunction(*MF, TransferMap, 1);
const char *RegNames[] = {"RAX", "HAX", "EAX", "AX", "AH", "AL"};
EXPECT_TRUE(MTracker->getNumLocs() == 7);
for (const char *RegName : RegNames) {
Register R = getRegByName(RegName);
ASSERT_TRUE(MTracker->isRegisterTracked(R));
LocIdx L = MTracker->getRegMLoc(R);
ValueIDNum V = MTracker->readReg(R);
ValueIDNum ToCmp(0, 1, L);
EXPECT_EQ(V, ToCmp);
}
MF = readMIRBlock(
" $rax = MOV64ri 0\n"
" $al = MOV8ri 0\n"
" RET64 $rax\n");
setupLDVObj(MF);
TransferMap.clear();
TransferMap.resize(1);
produceMLocTransferFunction(*MF, TransferMap, 1);
auto TestRegSetSite = [&](const char *Name, unsigned InstrNum) {
Register R = getRegByName(Name);
ASSERT_TRUE(MTracker->isRegisterTracked(R));
LocIdx L = MTracker->getRegMLoc(R);
ValueIDNum V = MTracker->readMLoc(L);
ValueIDNum ToCmp(0, InstrNum, L);
EXPECT_EQ(V, ToCmp);
};
TestRegSetSite("AL", 2);
TestRegSetSite("AH", 1);
TestRegSetSite("AX", 2);
TestRegSetSite("EAX", 2);
TestRegSetSite("HAX", 1);
TestRegSetSite("RAX", 2);
MF = readMIRBlock(
" $rax = MOV64ri 0\n" " $rbx = MOV64ri 0\n" " $rcx = MOV64ri 0\n" " $rdi = MOV64ri 0\n" " $rsi = MOV64ri 0\n" " CALL64r $rax, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit $rsi, implicit-def $rsp, implicit-def $ssp, implicit-def $rax, implicit-def $esp, implicit-def $sp\n\n\n\n" " RET64 $rax\n"); setupLDVObj(MF);
TransferMap.clear();
TransferMap.resize(1);
produceMLocTransferFunction(*MF, TransferMap, 1);
const char *RegsSetInCall[] = {"AL", "AH", "AX", "EAX", "HAX", "RAX",
"DIL", "DIH", "DI", "EDI", "HDI", "RDI",
"SIL", "SIH", "SI", "ESI", "HSI", "RSI",
"CL", "CH", "CX", "ECX", "HCX", "RCX"};
for (const char *RegSetInCall : RegsSetInCall)
TestRegSetSite(RegSetInCall, 6);
const char *RegsLeftAlone[] = {"BL", "BH", "BX", "EBX", "HBX", "RBX"};
for (const char *RegLeftAlone : RegsLeftAlone)
TestRegSetSite(RegLeftAlone, 2);
TestRegSetSite("RSP", 0);
EXPECT_FALSE(MTracker->isRegisterTracked(getRegByName("ESP")));
EXPECT_FALSE(MTracker->isRegisterTracked(getRegByName("SP")));
EXPECT_FALSE(MTracker->isRegisterTracked(getRegByName("SPL")));
EXPECT_FALSE(MTracker->isRegisterTracked(getRegByName("SPH")));
EXPECT_FALSE(MTracker->isRegisterTracked(getRegByName("HSP")));
EXPECT_EQ(32u, MTracker->getNumLocs());
MF = readMIRBlock(
" DBG_PHI $rdi, 0\n"
" RET64\n");
setupLDVObj(MF);
TransferMap.clear();
TransferMap.resize(1);
produceMLocTransferFunction(*MF, TransferMap, 1);
EXPECT_EQ(7u, MTracker->getNumLocs());
const char *DIRegs[] = {"DIL", "DIH", "DI", "EDI", "HDI", "RDI"};
for (const char *DIReg : DIRegs)
TestRegSetSite(DIReg, 0);
}
TEST_F(InstrRefLDVTest, MTransferMeta) {
SmallVector<MLocTransferMap, 1> TransferMap;
MachineFunction *MF = readMIRBlock(
" $rax = MOV64ri 0\n"
" $rax = IMPLICIT_DEF\n"
" $rax = KILL killed $rax\n"
" RET64 $rax\n");
setupLDVObj(MF);
TransferMap.clear();
TransferMap.resize(1);
produceMLocTransferFunction(*MF, TransferMap, 1);
LocIdx RaxLoc = MTracker->getRegMLoc(getRegByName("RAX"));
ValueIDNum V = MTracker->readMLoc(RaxLoc);
ValueIDNum Cmp(0, 1, RaxLoc);
EXPECT_EQ(Cmp, V);
}
TEST_F(InstrRefLDVTest, MTransferCopies) {
SmallVector<MLocTransferMap, 1> TransferMap;
MachineFunction *MF = readMIRBlock(
" $rax = MOV64ri 0\n"
" MOV64mr $rsp, 1, $noreg, 16, $noreg, $rax :: (store 8 into %stack.0)\n"
" RET64 $rax\n");
setupLDVObj(MF);
TransferMap.clear();
TransferMap.resize(1);
produceMLocTransferFunction(*MF, TransferMap, 1);
SpillLoc L = {getRegByName("RSP"), StackOffset::getFixed(-8)};
SpillLocationNo SpillNo = *MTracker->getOrTrackSpillLoc(L);
unsigned SpillLocID = MTracker->getLocID(SpillNo, {64, 0});
LocIdx SpillLoc = MTracker->getSpillMLoc(SpillLocID);
ValueIDNum V = MTracker->readMLoc(SpillLoc);
Register RAX = getRegByName("RAX");
LocIdx RaxLoc = MTracker->getRegMLoc(RAX);
ValueIDNum Cmp(0, 1, RaxLoc);
EXPECT_EQ(V, Cmp);
MF = readMIRBlock(
" $rax = MOV64ri 0\n"
" MOV64mr $rsp, 1, $noreg, 16, $noreg, $rax :: (store 8 into %stack.0)\n"
" $rbx = MOV64rm $rsp, 1, $noreg, 0, $noreg :: (load 8 from %stack.0)\n"
" RET64\n");
setupLDVObj(MF);
TransferMap.clear();
TransferMap.resize(1);
produceMLocTransferFunction(*MF, TransferMap, 1);
RAX = getRegByName("RAX");
RaxLoc = MTracker->getRegMLoc(RAX);
Register RBX = getRegByName("RBX");
LocIdx RbxLoc = MTracker->getRegMLoc(RBX);
Cmp = ValueIDNum(0, 1, RaxLoc);
ValueIDNum RbxVal = MTracker->readMLoc(RbxLoc);
EXPECT_EQ(RbxVal, Cmp);
MF = readMIRBlock(
" $rax = MOV64ri 0\n"
" $rcx = COPY $rax\n"
" $rbx = MOV64rr $rcx\n"
" RET64\n");
setupLDVObj(MF);
TransferMap.clear();
TransferMap.resize(1);
produceMLocTransferFunction(*MF, TransferMap, 1);
const char *ARegs[] = {"AL", "AH", "AX", "EAX", "HAX", "RAX"};
const char *BRegs[] = {"BL", "BH", "BX", "EBX", "HBX", "RBX"};
const char *CRegs[] = {"CL", "CH", "CX", "ECX", "HCX", "RCX"};
auto CheckReg = [&](unsigned int I) {
LocIdx A = MTracker->getRegMLoc(getRegByName(ARegs[I]));
LocIdx B = MTracker->getRegMLoc(getRegByName(BRegs[I]));
LocIdx C = MTracker->getRegMLoc(getRegByName(CRegs[I]));
ValueIDNum ARefVal(0, 1, A);
ValueIDNum AVal = MTracker->readMLoc(A);
ValueIDNum BVal = MTracker->readMLoc(B);
ValueIDNum CVal = MTracker->readMLoc(C);
EXPECT_EQ(ARefVal, AVal);
EXPECT_EQ(ARefVal, BVal);
EXPECT_EQ(ARefVal, CVal);
};
for (unsigned int I = 0; I < 6; ++I)
CheckReg(I);
MF = readMIRBlock(
" $rax = MOV64ri 0\n"
" $ecx = COPY $eax\n"
" RET64\n");
setupLDVObj(MF);
TransferMap.clear();
TransferMap.resize(1);
produceMLocTransferFunction(*MF, TransferMap, 1);
for (unsigned int I = 0; I < 4; ++I) {
LocIdx A = MTracker->getRegMLoc(getRegByName(ARegs[I]));
LocIdx C = MTracker->getRegMLoc(getRegByName(CRegs[I]));
ValueIDNum ARefVal(0, 1, A);
ValueIDNum AVal = MTracker->readMLoc(A);
ValueIDNum CVal = MTracker->readMLoc(C);
EXPECT_EQ(ARefVal, AVal);
EXPECT_EQ(ARefVal, CVal);
}
LocIdx RcxLoc = MTracker->getRegMLoc(getRegByName("RCX"));
ValueIDNum RcxVal = MTracker->readMLoc(RcxLoc);
ValueIDNum RcxDefVal(0, 2, RcxLoc); EXPECT_EQ(RcxVal, RcxDefVal);
}
TEST_F(InstrRefLDVTest, MTransferSubregSpills) {
SmallVector<MLocTransferMap, 1> TransferMap;
MachineFunction *MF = readMIRBlock(
" $rax = MOV64ri 0\n"
" MOV64mr $rsp, 1, $noreg, 16, $noreg, $rax :: (store 8 into %stack.0)\n"
" $rbx = MOV64rm $rsp, 1, $noreg, 0, $noreg :: (load 8 from %stack.0)\n"
" RET64\n");
setupLDVObj(MF);
TransferMap.clear();
TransferMap.resize(1);
produceMLocTransferFunction(*MF, TransferMap, 1);
const char *ARegs[] = {"AL", "AH", "AX", "EAX", "HAX", "RAX"};
const char *BRegs[] = {"BL", "BH", "BX", "EBX", "HBX", "RBX"};
for (unsigned int I = 0; I < 6; ++I) {
LocIdx A = MTracker->getRegMLoc(getRegByName(ARegs[I]));
LocIdx B = MTracker->getRegMLoc(getRegByName(BRegs[I]));
EXPECT_EQ(MTracker->readMLoc(A), MTracker->readMLoc(B));
}
MLocTracker::StackSlotPos SubRegIdxes[] = {{8, 0}, {8, 8}, {16, 0}, {32, 0}, {64, 0}};
const char *SubRegNames[] = {"AL", "AH", "AX", "EAX", "RAX"};
for (unsigned int I = 0; I < 5; ++I) {
LocIdx RegLoc = MTracker->getRegMLoc(getRegByName(SubRegNames[I]));
ValueIDNum DefNum(0, 1, RegLoc);
SpillLoc L = {getRegByName("RSP"), StackOffset::getFixed(-8)};
SpillLocationNo SpillNo = *MTracker->getOrTrackSpillLoc(L);
unsigned SpillID = MTracker->getLocID(SpillNo, SubRegIdxes[I]);
LocIdx SpillLoc = MTracker->getSpillMLoc(SpillID);
ValueIDNum SpillValue = MTracker->readMLoc(SpillLoc);
EXPECT_EQ(DefNum, SpillValue);
}
MF = readMIRBlock(
" $rax = MOV64ri 0\n"
" MOV64mr $rsp, 1, $noreg, 16, $noreg, $rax :: (store 8 into %stack.0)\n"
" MOV32mr $rsp, 1, $noreg, 16, $noreg, $eax :: (store 4 into %stack.0)\n"
" $rbx = MOV64rm $rsp, 1, $noreg, 0, $noreg :: (load 8 from %stack.0)\n"
" RET64\n");
setupLDVObj(MF);
TransferMap.clear();
TransferMap.resize(1);
produceMLocTransferFunction(*MF, TransferMap, 1);
for (unsigned int I = 0; I < 5; ++I) {
LocIdx A = MTracker->getRegMLoc(getRegByName(ARegs[I]));
LocIdx B = MTracker->getRegMLoc(getRegByName(BRegs[I]));
EXPECT_EQ(MTracker->readMLoc(A), MTracker->readMLoc(B));
}
SpillLoc L = {getRegByName("RSP"), StackOffset::getFixed(-8)};
SpillLocationNo SpillNo = *MTracker->getOrTrackSpillLoc(L);
unsigned SpillID = MTracker->getLocID(SpillNo, {64, 0});
LocIdx Spill64Loc = MTracker->getSpillMLoc(SpillID);
ValueIDNum DefAtSpill64(0, 3, Spill64Loc);
LocIdx RbxLoc = MTracker->getRegMLoc(getRegByName("RBX"));
EXPECT_EQ(MTracker->readMLoc(RbxLoc), DefAtSpill64);
for (unsigned int I = 0; I < 4; ++I) {
LocIdx RegLoc = MTracker->getRegMLoc(getRegByName(SubRegNames[I]));
ValueIDNum DefNum(0, 1, RegLoc);
SpillNo = *MTracker->getOrTrackSpillLoc(L);
SpillID = MTracker->getLocID(SpillNo, SubRegIdxes[I]);
LocIdx SpillLoc = MTracker->getSpillMLoc(SpillID);
ValueIDNum SpillValue = MTracker->readMLoc(SpillLoc);
EXPECT_EQ(DefNum, SpillValue);
}
ValueIDNum SpillValue = MTracker->readMLoc(Spill64Loc);
EXPECT_EQ(SpillValue, DefAtSpill64);
MF = readMIRBlock(
" $rax = MOV64ri 0\n"
" MOV64mr $rsp, 1, $noreg, 16, $noreg, $rax :: (store 8 into %stack.0)\n"
" $xmm0 = IMPLICIT_DEF\n"
" MOVUPDmr $rsp, 1, $noreg, 16, $noreg, killed $xmm0 :: (store (s128) into %stack.0)\n"
" $rbx = MOV64rm $rsp, 1, $noreg, 0, $noreg :: (load 8 from %stack.0)\n"
" RET64\n");
setupLDVObj(MF);
TransferMap.clear();
TransferMap.resize(1);
produceMLocTransferFunction(*MF, TransferMap, 1);
for (unsigned int I = 0; I < 5; ++I) {
SpillLocationNo SpillNo = *MTracker->getOrTrackSpillLoc(L);
unsigned SpillID = MTracker->getLocID(SpillNo, SubRegIdxes[I]);
LocIdx SpillLoc = MTracker->getSpillMLoc(SpillID);
ValueIDNum SpillValue = MTracker->readMLoc(SpillLoc);
ValueIDNum SpillDef(0, 4, SpillLoc);
EXPECT_EQ(SpillValue, SpillDef);
}
SpillNo = *MTracker->getOrTrackSpillLoc(L);
SpillID = MTracker->getLocID(SpillNo, {128, 0});
LocIdx Spill128Loc = MTracker->getSpillMLoc(SpillID);
SpillValue = MTracker->readMLoc(Spill128Loc);
Register XMM0 = getRegByName("XMM0");
LocIdx Xmm0Loc = MTracker->getRegMLoc(XMM0);
EXPECT_EQ(ValueIDNum(0, 0, Xmm0Loc), SpillValue);
MF = readMIRBlock(
" $rax = MOV64ri 0\n"
" MOV8mr $rsp, 1, $noreg, 16, $noreg, $ah :: (store 1 into %stack.0)\n"
" $al = MOV8rm $rsp, 1, $noreg, 0, $noreg :: (load 1 from %stack.0)\n"
" RET64\n");
setupLDVObj(MF);
TransferMap.clear();
TransferMap.resize(1);
produceMLocTransferFunction(*MF, TransferMap, 1);
Register AL = getRegByName("AL");
Register AH = getRegByName("AH");
LocIdx AlLoc = MTracker->getRegMLoc(AL);
LocIdx AhLoc = MTracker->getRegMLoc(AH);
ValueIDNum AHDef(0, 1, AhLoc);
ValueIDNum ALValue = MTracker->readMLoc(AlLoc);
EXPECT_EQ(ALValue, AHDef);
}
TEST_F(InstrRefLDVTest, MLocSingleBlock) {
setupSingleBlock();
ASSERT_TRUE(MTracker->getNumLocs() == 1);
LocIdx RspLoc(0);
FuncValueTable MOutLocs, MInLocs;
std::tie(MOutLocs, MInLocs) = allocValueTables(1, 2);
SmallVector<MLocTransferMap, 1> TransferFunc;
TransferFunc.resize(1);
buildMLocValueMap(MInLocs, MOutLocs, TransferFunc);
EXPECT_EQ(MInLocs[0][0], ValueIDNum(0, 0, RspLoc));
EXPECT_EQ(MOutLocs[0][0], ValueIDNum(0, 0, RspLoc));
initValueArray(MInLocs, 1, 2);
initValueArray(MOutLocs, 1, 2);
MInLocs[0][0] = ValueIDNum(0, 1, RspLoc);
buildMLocValueMap(MInLocs, MOutLocs, TransferFunc);
EXPECT_EQ(MInLocs[0][0], ValueIDNum(0, 0, RspLoc));
EXPECT_EQ(MOutLocs[0][0], ValueIDNum(0, 0, RspLoc));
TransferFunc[0].insert({RspLoc, ValueIDNum(0, 1, RspLoc)});
initValueArray(MInLocs, 1, 2);
initValueArray(MOutLocs, 1, 2);
buildMLocValueMap(MInLocs, MOutLocs, TransferFunc);
EXPECT_EQ(MInLocs[0][0], ValueIDNum(0, 0, RspLoc));
EXPECT_EQ(MOutLocs[0][0], ValueIDNum(0, 1, RspLoc));
TransferFunc[0].clear();
Register RAX = getRegByName("RAX");
LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX);
TransferFunc[0].insert({RspLoc, ValueIDNum(0, 1, RspLoc)});
TransferFunc[0].insert({RaxLoc, ValueIDNum(0, 0, RspLoc)});
initValueArray(MInLocs, 1, 2);
initValueArray(MOutLocs, 1, 2);
buildMLocValueMap(MInLocs, MOutLocs, TransferFunc);
EXPECT_EQ(MInLocs[0][0], ValueIDNum(0, 0, RspLoc));
EXPECT_EQ(MInLocs[0][1], ValueIDNum(0, 0, RaxLoc));
EXPECT_EQ(MOutLocs[0][0], ValueIDNum(0, 1, RspLoc));
EXPECT_EQ(MOutLocs[0][1], ValueIDNum(0, 0, RspLoc)); TransferFunc[0].clear();
}
TEST_F(InstrRefLDVTest, MLocDiamondBlocks) {
setupDiamondBlocks();
ASSERT_TRUE(MTracker->getNumLocs() == 1);
LocIdx RspLoc(0);
Register RAX = getRegByName("RAX");
LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX);
FuncValueTable MInLocs, MOutLocs;
std::tie(MInLocs, MOutLocs) = allocValueTables(4, 2);
SmallVector<MLocTransferMap, 1> TransferFunc;
TransferFunc.resize(4);
unsigned EntryBlk = 0, BrBlk1 = 1, BrBlk2 = 2, RetBlk = 3;
ValueIDNum LiveInRsp(EntryBlk, 0, RspLoc);
ValueIDNum RspDefInBlk0(EntryBlk, 1, RspLoc);
ValueIDNum RspDefInBlk1(BrBlk1, 1, RspLoc);
ValueIDNum RspDefInBlk2(BrBlk2, 1, RspLoc);
ValueIDNum RspPHIInBlk3(RetBlk, 0, RspLoc);
ValueIDNum RaxLiveInBlk1(BrBlk1, 0, RaxLoc);
ValueIDNum RaxLiveInBlk2(BrBlk2, 0, RaxLoc);
initValueArray(MInLocs, 4, 2);
initValueArray(MOutLocs, 4, 2);
buildMLocValueMap(MInLocs, MOutLocs, TransferFunc);
EXPECT_EQ(MInLocs[0][0], LiveInRsp);
EXPECT_EQ(MInLocs[1][0], LiveInRsp);
EXPECT_EQ(MInLocs[2][0], LiveInRsp);
EXPECT_EQ(MInLocs[3][0], LiveInRsp);
EXPECT_EQ(MOutLocs[0][0], LiveInRsp);
EXPECT_EQ(MOutLocs[1][0], LiveInRsp);
EXPECT_EQ(MOutLocs[2][0], LiveInRsp);
EXPECT_EQ(MOutLocs[3][0], LiveInRsp);
TransferFunc[0].insert({RspLoc, RspDefInBlk0});
initValueArray(MInLocs, 4, 2);
initValueArray(MOutLocs, 4, 2);
buildMLocValueMap(MInLocs, MOutLocs, TransferFunc);
EXPECT_EQ(MInLocs[0][0], LiveInRsp);
EXPECT_EQ(MInLocs[1][0], RspDefInBlk0);
EXPECT_EQ(MInLocs[2][0], RspDefInBlk0);
EXPECT_EQ(MInLocs[3][0], RspDefInBlk0);
EXPECT_EQ(MOutLocs[0][0], RspDefInBlk0);
EXPECT_EQ(MOutLocs[1][0], RspDefInBlk0);
EXPECT_EQ(MOutLocs[2][0], RspDefInBlk0);
EXPECT_EQ(MOutLocs[3][0], RspDefInBlk0);
TransferFunc[0].clear();
TransferFunc[0].insert({RspLoc, RspDefInBlk0});
TransferFunc[1].insert({RspLoc, RspDefInBlk1});
initValueArray(MInLocs, 4, 2);
initValueArray(MOutLocs, 4, 2);
buildMLocValueMap(MInLocs, MOutLocs, TransferFunc);
EXPECT_EQ(MInLocs[0][0], LiveInRsp);
EXPECT_EQ(MInLocs[1][0], RspDefInBlk0);
EXPECT_EQ(MInLocs[2][0], RspDefInBlk0);
EXPECT_EQ(MInLocs[3][0], RspPHIInBlk3);
EXPECT_EQ(MOutLocs[0][0], RspDefInBlk0);
EXPECT_EQ(MOutLocs[1][0], RspDefInBlk1);
EXPECT_EQ(MOutLocs[2][0], RspDefInBlk0);
EXPECT_EQ(MOutLocs[3][0], RspPHIInBlk3);
TransferFunc[0].clear();
TransferFunc[1].clear();
TransferFunc[0].insert({RspLoc, RspDefInBlk0});
TransferFunc[1].insert({RspLoc, RspDefInBlk1});
TransferFunc[2].insert({RspLoc, RspDefInBlk2});
initValueArray(MInLocs, 4, 2);
initValueArray(MOutLocs, 4, 2);
buildMLocValueMap(MInLocs, MOutLocs, TransferFunc);
EXPECT_EQ(MInLocs[0][0], LiveInRsp);
EXPECT_EQ(MInLocs[1][0], RspDefInBlk0);
EXPECT_EQ(MInLocs[2][0], RspDefInBlk0);
EXPECT_EQ(MInLocs[3][0], RspPHIInBlk3);
EXPECT_EQ(MOutLocs[0][0], RspDefInBlk0);
EXPECT_EQ(MOutLocs[1][0], RspDefInBlk1);
EXPECT_EQ(MOutLocs[2][0], RspDefInBlk2);
EXPECT_EQ(MOutLocs[3][0], RspPHIInBlk3);
TransferFunc[0].clear();
TransferFunc[1].clear();
TransferFunc[2].clear();
TransferFunc[0].insert({RspLoc, RspDefInBlk0});
TransferFunc[0].insert({RaxLoc, LiveInRsp});
TransferFunc[1].insert({RspLoc, RaxLiveInBlk1});
TransferFunc[2].insert({RspLoc, RaxLiveInBlk2});
initValueArray(MInLocs, 4, 2);
initValueArray(MOutLocs, 4, 2);
buildMLocValueMap(MInLocs, MOutLocs, TransferFunc);
EXPECT_EQ(MInLocs[0][0], LiveInRsp);
EXPECT_EQ(MInLocs[1][0], RspDefInBlk0);
EXPECT_EQ(MInLocs[2][0], RspDefInBlk0);
EXPECT_EQ(MInLocs[3][0], LiveInRsp);
EXPECT_EQ(MOutLocs[0][0], RspDefInBlk0);
EXPECT_EQ(MOutLocs[1][0], LiveInRsp);
EXPECT_EQ(MOutLocs[2][0], LiveInRsp);
EXPECT_EQ(MOutLocs[3][0], LiveInRsp);
TransferFunc[0].clear();
TransferFunc[1].clear();
TransferFunc[2].clear();
}
TEST_F(InstrRefLDVTest, MLocDiamondSpills) {
setupDiamondBlocks();
ASSERT_TRUE(MTracker->getNumLocs() == 1);
LocIdx RspLoc(0);
SpillLoc SL = {getRegByName("RSP"), StackOffset::getFixed(-8)};
SpillLocationNo SpillNo = *MTracker->getOrTrackSpillLoc(SL);
ASSERT_EQ(MTracker->getNumLocs(), 11u);
unsigned ALID = MTracker->getLocID(SpillNo, {8, 0});
unsigned AHID = MTracker->getLocID(SpillNo, {8, 8});
unsigned AXID = MTracker->getLocID(SpillNo, {16, 0});
unsigned EAXID = MTracker->getLocID(SpillNo, {32, 0});
unsigned HAXID = MTracker->getLocID(SpillNo, {16, 16});
unsigned RAXID = MTracker->getLocID(SpillNo, {64, 0});
LocIdx ALStackLoc = MTracker->getSpillMLoc(ALID);
LocIdx AHStackLoc = MTracker->getSpillMLoc(AHID);
LocIdx AXStackLoc = MTracker->getSpillMLoc(AXID);
LocIdx EAXStackLoc = MTracker->getSpillMLoc(EAXID);
LocIdx HAXStackLoc = MTracker->getSpillMLoc(HAXID);
LocIdx RAXStackLoc = MTracker->getSpillMLoc(RAXID);
FuncValueTable MInLocs, MOutLocs;
std::tie(MInLocs, MOutLocs) = allocValueTables(4, 11);
SmallVector<MLocTransferMap, 1> TransferFunc;
TransferFunc.resize(4);
unsigned EntryBlk = 0, Blk1 = 1, RetBlk = 3;
ValueIDNum LiveInRsp(EntryBlk, 0, RspLoc);
ValueIDNum ALLiveIn(EntryBlk, 0, ALStackLoc);
ValueIDNum AHLiveIn(EntryBlk, 0, AHStackLoc);
ValueIDNum HAXLiveIn(EntryBlk, 0, HAXStackLoc);
ValueIDNum ALPHI(RetBlk, 0, ALStackLoc);
ValueIDNum AXPHI(RetBlk, 0, AXStackLoc);
ValueIDNum EAXPHI(RetBlk, 0, EAXStackLoc);
ValueIDNum HAXPHI(RetBlk, 0, HAXStackLoc);
ValueIDNum RAXPHI(RetBlk, 0, RAXStackLoc);
ValueIDNum ALDefInBlk1(Blk1, 1, ALStackLoc);
ValueIDNum HAXDefInBlk1(Blk1, 1, HAXStackLoc);
SmallPtrSet<MachineBasicBlock *, 4> AllBlocks{MBB0, MBB1, MBB2, MBB3};
TransferFunc[1].insert({ALStackLoc, ALDefInBlk1});
TransferFunc[1].insert({HAXStackLoc, HAXDefInBlk1});
initValueArray(MInLocs, 4, 11);
placeMLocPHIs(*MF, AllBlocks, MInLocs, TransferFunc);
EXPECT_EQ(MInLocs[3][ALStackLoc.asU64()], ALPHI);
EXPECT_EQ(MInLocs[3][AXStackLoc.asU64()], AXPHI);
EXPECT_EQ(MInLocs[3][EAXStackLoc.asU64()], EAXPHI);
EXPECT_EQ(MInLocs[3][HAXStackLoc.asU64()], HAXPHI);
EXPECT_EQ(MInLocs[3][RAXStackLoc.asU64()], RAXPHI);
EXPECT_EQ(MInLocs[3][AHStackLoc.asU64()], ValueIDNum::EmptyValue);
}
TEST_F(InstrRefLDVTest, MLocSimpleLoop) {
setupSimpleLoop();
ASSERT_TRUE(MTracker->getNumLocs() == 1);
LocIdx RspLoc(0);
Register RAX = getRegByName("RAX");
LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX);
FuncValueTable MInLocs, MOutLocs;
std::tie(MInLocs, MOutLocs) = allocValueTables(3, 2);
SmallVector<MLocTransferMap, 1> TransferFunc;
TransferFunc.resize(3);
unsigned EntryBlk = 0, LoopBlk = 1, RetBlk = 2;
ValueIDNum LiveInRsp(EntryBlk, 0, RspLoc);
ValueIDNum RspPHIInBlk1(LoopBlk, 0, RspLoc);
ValueIDNum RspDefInBlk1(LoopBlk, 1, RspLoc);
ValueIDNum LiveInRax(EntryBlk, 0, RaxLoc);
ValueIDNum RaxPHIInBlk1(LoopBlk, 0, RaxLoc);
ValueIDNum RaxPHIInBlk2(RetBlk, 0, RaxLoc);
initValueArray(MInLocs, 3, 2);
initValueArray(MOutLocs, 3, 2);
buildMLocValueMap(MInLocs, MOutLocs, TransferFunc);
EXPECT_EQ(MInLocs[0][0], LiveInRsp);
EXPECT_EQ(MInLocs[1][0], LiveInRsp);
EXPECT_EQ(MInLocs[2][0], LiveInRsp);
EXPECT_EQ(MOutLocs[0][0], LiveInRsp);
EXPECT_EQ(MOutLocs[1][0], LiveInRsp);
EXPECT_EQ(MOutLocs[2][0], LiveInRsp);
TransferFunc[1].insert({RspLoc, RspDefInBlk1});
TransferFunc[1].insert({RaxLoc, RspPHIInBlk1});
TransferFunc[2].insert({RspLoc, RaxPHIInBlk2});
initValueArray(MInLocs, 3, 2);
initValueArray(MOutLocs, 3, 2);
buildMLocValueMap(MInLocs, MOutLocs, TransferFunc);
EXPECT_EQ(MInLocs[0][0], LiveInRsp);
EXPECT_EQ(MInLocs[1][0], RspPHIInBlk1);
EXPECT_EQ(MInLocs[2][0], RspDefInBlk1);
EXPECT_EQ(MOutLocs[0][0], LiveInRsp);
EXPECT_EQ(MOutLocs[1][0], RspDefInBlk1);
EXPECT_EQ(MOutLocs[2][0], RspPHIInBlk1);
EXPECT_EQ(MInLocs[0][1], LiveInRax);
EXPECT_EQ(MInLocs[1][1], RaxPHIInBlk1);
EXPECT_EQ(MInLocs[2][1], RspPHIInBlk1);
EXPECT_EQ(MOutLocs[0][1], LiveInRax);
EXPECT_EQ(MOutLocs[1][1], RspPHIInBlk1);
EXPECT_EQ(MOutLocs[2][1], RspPHIInBlk1);
TransferFunc[1].clear();
TransferFunc[2].clear();
TransferFunc[0].insert({RaxLoc, LiveInRsp});
TransferFunc[1].insert({RspLoc, RaxPHIInBlk1});
initValueArray(MInLocs, 3, 2);
initValueArray(MOutLocs, 3, 2);
buildMLocValueMap(MInLocs, MOutLocs, TransferFunc);
EXPECT_EQ(MInLocs[0][0], LiveInRsp);
EXPECT_EQ(MInLocs[1][0], LiveInRsp);
EXPECT_EQ(MInLocs[2][0], LiveInRsp);
EXPECT_EQ(MOutLocs[0][0], LiveInRsp);
EXPECT_EQ(MOutLocs[1][0], LiveInRsp);
EXPECT_EQ(MOutLocs[2][0], LiveInRsp);
EXPECT_EQ(MInLocs[0][1], LiveInRax);
EXPECT_EQ(MInLocs[1][1], LiveInRsp);
EXPECT_EQ(MInLocs[2][1], LiveInRsp);
EXPECT_EQ(MOutLocs[0][1], LiveInRsp);
EXPECT_EQ(MOutLocs[1][1], LiveInRsp);
EXPECT_EQ(MOutLocs[2][1], LiveInRsp);
TransferFunc[0].clear();
TransferFunc[1].clear();
}
TEST_F(InstrRefLDVTest, MLocNestedLoop) {
setupNestedLoops();
ASSERT_TRUE(MTracker->getNumLocs() == 1);
LocIdx RspLoc(0);
Register RAX = getRegByName("RAX");
LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX);
FuncValueTable MInLocs, MOutLocs;
std::tie(MInLocs, MOutLocs) = allocValueTables(5, 2);
SmallVector<MLocTransferMap, 1> TransferFunc;
TransferFunc.resize(5);
unsigned EntryBlk = 0, Loop1Blk = 1, Loop2Blk = 2, JoinBlk = 3;
ValueIDNum LiveInRsp(EntryBlk, 0, RspLoc);
ValueIDNum RspPHIInBlk1(Loop1Blk, 0, RspLoc);
ValueIDNum RspDefInBlk1(Loop1Blk, 1, RspLoc);
ValueIDNum RspPHIInBlk2(Loop2Blk, 0, RspLoc);
ValueIDNum RspDefInBlk2(Loop2Blk, 1, RspLoc);
ValueIDNum RspDefInBlk3(JoinBlk, 1, RspLoc);
ValueIDNum LiveInRax(EntryBlk, 0, RaxLoc);
ValueIDNum RaxPHIInBlk1(Loop1Blk, 0, RaxLoc);
ValueIDNum RaxPHIInBlk2(Loop2Blk, 0, RaxLoc);
initValueArray(MInLocs, 5, 2);
initValueArray(MOutLocs, 5, 2);
buildMLocValueMap(MInLocs, MOutLocs, TransferFunc);
EXPECT_EQ(MInLocs[0][0], LiveInRsp);
EXPECT_EQ(MInLocs[1][0], LiveInRsp);
EXPECT_EQ(MInLocs[2][0], LiveInRsp);
EXPECT_EQ(MInLocs[3][0], LiveInRsp);
EXPECT_EQ(MInLocs[4][0], LiveInRsp);
EXPECT_EQ(MOutLocs[0][0], LiveInRsp);
EXPECT_EQ(MOutLocs[1][0], LiveInRsp);
EXPECT_EQ(MOutLocs[2][0], LiveInRsp);
EXPECT_EQ(MOutLocs[3][0], LiveInRsp);
EXPECT_EQ(MOutLocs[4][0], LiveInRsp);
TransferFunc[2].insert({RspLoc, RspDefInBlk2});
initValueArray(MInLocs, 5, 2);
initValueArray(MOutLocs, 5, 2);
buildMLocValueMap(MInLocs, MOutLocs, TransferFunc);
EXPECT_EQ(MInLocs[0][0], LiveInRsp);
EXPECT_EQ(MInLocs[1][0], RspPHIInBlk1);
EXPECT_EQ(MInLocs[2][0], RspPHIInBlk2);
EXPECT_EQ(MInLocs[3][0], RspDefInBlk2);
EXPECT_EQ(MInLocs[4][0], RspDefInBlk2);
EXPECT_EQ(MOutLocs[0][0], LiveInRsp);
EXPECT_EQ(MOutLocs[1][0], RspPHIInBlk1);
EXPECT_EQ(MOutLocs[2][0], RspDefInBlk2);
EXPECT_EQ(MOutLocs[3][0], RspDefInBlk2);
EXPECT_EQ(MOutLocs[4][0], RspDefInBlk2);
TransferFunc[2].clear();
TransferFunc[1].insert({RspLoc, RspDefInBlk1});
TransferFunc[2].insert({RspLoc, RspDefInBlk2});
initValueArray(MInLocs, 5, 2);
initValueArray(MOutLocs, 5, 2);
buildMLocValueMap(MInLocs, MOutLocs, TransferFunc);
EXPECT_EQ(MInLocs[0][0], LiveInRsp);
EXPECT_EQ(MInLocs[1][0], RspPHIInBlk1);
EXPECT_EQ(MInLocs[2][0], RspPHIInBlk2);
EXPECT_EQ(MInLocs[3][0], RspDefInBlk2);
EXPECT_EQ(MInLocs[4][0], RspDefInBlk2);
EXPECT_EQ(MOutLocs[0][0], LiveInRsp);
EXPECT_EQ(MOutLocs[1][0], RspDefInBlk1);
EXPECT_EQ(MOutLocs[2][0], RspDefInBlk2);
EXPECT_EQ(MOutLocs[3][0], RspDefInBlk2);
EXPECT_EQ(MOutLocs[4][0], RspDefInBlk2);
TransferFunc[1].clear();
TransferFunc[2].clear();
TransferFunc[1].insert({RspLoc, RspDefInBlk1});
TransferFunc[2].insert({RspLoc, RspDefInBlk2});
TransferFunc[3].insert({RspLoc, RspDefInBlk3});
initValueArray(MInLocs, 5, 2);
initValueArray(MOutLocs, 5, 2);
buildMLocValueMap(MInLocs, MOutLocs, TransferFunc);
EXPECT_EQ(MInLocs[0][0], LiveInRsp);
EXPECT_EQ(MInLocs[1][0], RspPHIInBlk1);
EXPECT_EQ(MInLocs[2][0], RspPHIInBlk2);
EXPECT_EQ(MInLocs[3][0], RspDefInBlk2);
EXPECT_EQ(MInLocs[4][0], RspDefInBlk3);
EXPECT_EQ(MOutLocs[0][0], LiveInRsp);
EXPECT_EQ(MOutLocs[1][0], RspDefInBlk1);
EXPECT_EQ(MOutLocs[2][0], RspDefInBlk2);
EXPECT_EQ(MOutLocs[3][0], RspDefInBlk3);
EXPECT_EQ(MOutLocs[4][0], RspDefInBlk3);
TransferFunc[1].clear();
TransferFunc[2].clear();
TransferFunc[3].clear();
TransferFunc[1].insert({RspLoc, RspDefInBlk1});
TransferFunc[3].insert({RspLoc, RspDefInBlk3});
initValueArray(MInLocs, 5, 2);
initValueArray(MOutLocs, 5, 2);
buildMLocValueMap(MInLocs, MOutLocs, TransferFunc);
EXPECT_EQ(MInLocs[0][0], LiveInRsp);
EXPECT_EQ(MInLocs[1][0], RspPHIInBlk1);
EXPECT_EQ(MInLocs[2][0], RspDefInBlk1);
EXPECT_EQ(MInLocs[3][0], RspDefInBlk1);
EXPECT_EQ(MInLocs[4][0], RspDefInBlk3);
EXPECT_EQ(MOutLocs[0][0], LiveInRsp);
EXPECT_EQ(MOutLocs[1][0], RspDefInBlk1);
EXPECT_EQ(MOutLocs[2][0], RspDefInBlk1);
EXPECT_EQ(MOutLocs[3][0], RspDefInBlk3);
EXPECT_EQ(MOutLocs[4][0], RspDefInBlk3);
TransferFunc[1].clear();
TransferFunc[3].clear();
TransferFunc[1].insert({RspLoc, RspDefInBlk1});
TransferFunc[1].insert({RaxLoc, RspDefInBlk1});
TransferFunc[2].insert({RspLoc, RaxPHIInBlk2});
TransferFunc[3].insert({RspLoc, RspDefInBlk3});
initValueArray(MInLocs, 5, 2);
initValueArray(MOutLocs, 5, 2);
buildMLocValueMap(MInLocs, MOutLocs, TransferFunc);
EXPECT_EQ(MInLocs[0][0], LiveInRsp);
EXPECT_EQ(MInLocs[1][0], RspPHIInBlk1);
EXPECT_EQ(MInLocs[2][0], RspDefInBlk1);
EXPECT_EQ(MInLocs[3][0], RspDefInBlk1);
EXPECT_EQ(MInLocs[4][0], RspDefInBlk3);
EXPECT_EQ(MOutLocs[0][0], LiveInRsp);
EXPECT_EQ(MOutLocs[1][0], RspDefInBlk1);
EXPECT_EQ(MOutLocs[2][0], RspDefInBlk1);
EXPECT_EQ(MOutLocs[3][0], RspDefInBlk3);
EXPECT_EQ(MOutLocs[4][0], RspDefInBlk3);
EXPECT_EQ(MInLocs[2][1], RspDefInBlk1);
EXPECT_EQ(MOutLocs[1][1], RspDefInBlk1);
TransferFunc[1].clear();
TransferFunc[2].clear();
TransferFunc[3].clear();
TransferFunc[3].insert({RspLoc, RspDefInBlk3});
initValueArray(MInLocs, 5, 2);
initValueArray(MOutLocs, 5, 2);
buildMLocValueMap(MInLocs, MOutLocs, TransferFunc);
EXPECT_EQ(MInLocs[0][0], LiveInRsp);
EXPECT_EQ(MInLocs[1][0], RspPHIInBlk1);
EXPECT_EQ(MInLocs[2][0], RspPHIInBlk1);
EXPECT_EQ(MInLocs[3][0], RspPHIInBlk1);
EXPECT_EQ(MInLocs[4][0], RspDefInBlk3);
EXPECT_EQ(MOutLocs[0][0], LiveInRsp);
EXPECT_EQ(MOutLocs[1][0], RspPHIInBlk1);
EXPECT_EQ(MOutLocs[2][0], RspPHIInBlk1);
EXPECT_EQ(MOutLocs[3][0], RspDefInBlk3);
EXPECT_EQ(MOutLocs[4][0], RspDefInBlk3);
TransferFunc[3].clear();
TransferFunc[2].insert({RaxLoc, RspPHIInBlk2});
TransferFunc[3].insert({RspLoc, RspDefInBlk3});
initValueArray(MInLocs, 5, 2);
initValueArray(MOutLocs, 5, 2);
buildMLocValueMap(MInLocs, MOutLocs, TransferFunc);
EXPECT_EQ(MInLocs[0][1], LiveInRax);
EXPECT_EQ(MInLocs[1][1], RaxPHIInBlk1);
EXPECT_EQ(MInLocs[2][1], RaxPHIInBlk2);
EXPECT_EQ(MInLocs[3][1], RspPHIInBlk1);
EXPECT_EQ(MInLocs[4][1], RspPHIInBlk1);
EXPECT_EQ(MOutLocs[0][1], LiveInRax);
EXPECT_EQ(MOutLocs[1][1], RaxPHIInBlk1);
EXPECT_EQ(MOutLocs[2][1], RspPHIInBlk1);
EXPECT_EQ(MOutLocs[3][1], RspPHIInBlk1);
EXPECT_EQ(MOutLocs[4][1], RspPHIInBlk1);
TransferFunc[2].clear();
TransferFunc[3].clear();
}
TEST_F(InstrRefLDVTest, MLocNoDominatingLoop) {
setupNoDominatingLoop();
ASSERT_TRUE(MTracker->getNumLocs() == 1);
LocIdx RspLoc(0);
Register RAX = getRegByName("RAX");
LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX);
FuncValueTable MInLocs, MOutLocs;
std::tie(MInLocs, MOutLocs) = allocValueTables(5, 2);
SmallVector<MLocTransferMap, 1> TransferFunc;
TransferFunc.resize(5);
unsigned EntryBlk = 0, Head1Blk = 1, Head2Blk = 2, JoinBlk = 3;
ValueIDNum LiveInRsp(EntryBlk, 0, RspLoc);
ValueIDNum RspPHIInBlk1(Head1Blk, 0, RspLoc);
ValueIDNum RspDefInBlk1(Head1Blk, 1, RspLoc);
ValueIDNum RspPHIInBlk2(Head2Blk, 0, RspLoc);
ValueIDNum RspDefInBlk2(Head2Blk, 1, RspLoc);
ValueIDNum RspPHIInBlk3(JoinBlk, 0, RspLoc);
ValueIDNum RspDefInBlk3(JoinBlk, 1, RspLoc);
ValueIDNum RaxPHIInBlk1(Head1Blk, 0, RaxLoc);
ValueIDNum RaxPHIInBlk2(Head2Blk, 0, RaxLoc);
initValueArray(MInLocs, 5, 2);
initValueArray(MOutLocs, 5, 2);
buildMLocValueMap(MInLocs, MOutLocs, TransferFunc);
EXPECT_EQ(MInLocs[0][0], LiveInRsp);
EXPECT_EQ(MInLocs[1][0], LiveInRsp);
EXPECT_EQ(MInLocs[2][0], LiveInRsp);
EXPECT_EQ(MInLocs[3][0], LiveInRsp);
EXPECT_EQ(MInLocs[4][0], LiveInRsp);
EXPECT_EQ(MOutLocs[0][0], LiveInRsp);
EXPECT_EQ(MOutLocs[1][0], LiveInRsp);
EXPECT_EQ(MOutLocs[2][0], LiveInRsp);
EXPECT_EQ(MOutLocs[3][0], LiveInRsp);
EXPECT_EQ(MOutLocs[4][0], LiveInRsp);
TransferFunc[3].insert({RspLoc, RspDefInBlk3});
initValueArray(MInLocs, 5, 2);
initValueArray(MOutLocs, 5, 2);
buildMLocValueMap(MInLocs, MOutLocs, TransferFunc);
EXPECT_EQ(MInLocs[0][0], LiveInRsp);
EXPECT_EQ(MInLocs[1][0], RspPHIInBlk1);
EXPECT_EQ(MInLocs[2][0], RspPHIInBlk2);
EXPECT_EQ(MInLocs[3][0], RspPHIInBlk3);
EXPECT_EQ(MInLocs[4][0], RspDefInBlk3);
EXPECT_EQ(MOutLocs[0][0], LiveInRsp);
EXPECT_EQ(MOutLocs[1][0], RspPHIInBlk1);
EXPECT_EQ(MOutLocs[2][0], RspPHIInBlk2);
EXPECT_EQ(MOutLocs[3][0], RspDefInBlk3);
EXPECT_EQ(MOutLocs[4][0], RspDefInBlk3);
TransferFunc[3].clear();
TransferFunc[1].insert({RspLoc, RspDefInBlk1});
initValueArray(MInLocs, 5, 2);
initValueArray(MOutLocs, 5, 2);
buildMLocValueMap(MInLocs, MOutLocs, TransferFunc);
EXPECT_EQ(MInLocs[0][0], LiveInRsp);
EXPECT_EQ(MInLocs[1][0], RspPHIInBlk1);
EXPECT_EQ(MInLocs[2][0], RspPHIInBlk2);
EXPECT_EQ(MInLocs[3][0], RspPHIInBlk3);
EXPECT_EQ(MInLocs[4][0], RspPHIInBlk3);
EXPECT_EQ(MOutLocs[0][0], LiveInRsp);
EXPECT_EQ(MOutLocs[1][0], RspDefInBlk1);
EXPECT_EQ(MOutLocs[2][0], RspPHIInBlk2);
EXPECT_EQ(MOutLocs[3][0], RspPHIInBlk3);
EXPECT_EQ(MOutLocs[4][0], RspPHIInBlk3);
TransferFunc[1].clear();
TransferFunc[2].insert({RspLoc, RspDefInBlk2});
initValueArray(MInLocs, 5, 2);
initValueArray(MOutLocs, 5, 2);
buildMLocValueMap(MInLocs, MOutLocs, TransferFunc);
EXPECT_EQ(MInLocs[0][0], LiveInRsp);
EXPECT_EQ(MInLocs[1][0], RspPHIInBlk1);
EXPECT_EQ(MInLocs[2][0], RspPHIInBlk2);
EXPECT_EQ(MInLocs[3][0], RspPHIInBlk3);
EXPECT_EQ(MInLocs[4][0], RspPHIInBlk3);
EXPECT_EQ(MOutLocs[0][0], LiveInRsp);
EXPECT_EQ(MOutLocs[1][0], RspPHIInBlk1);
EXPECT_EQ(MOutLocs[2][0], RspDefInBlk2);
EXPECT_EQ(MOutLocs[3][0], RspPHIInBlk3);
EXPECT_EQ(MOutLocs[4][0], RspPHIInBlk3);
TransferFunc[2].clear();
TransferFunc[0].insert({RaxLoc, LiveInRsp});
TransferFunc[1].insert({RspLoc, RaxPHIInBlk1});
TransferFunc[2].insert({RspLoc, RaxPHIInBlk2});
TransferFunc[3].insert({RspLoc, RspDefInBlk3});
initValueArray(MInLocs, 5, 2);
initValueArray(MOutLocs, 5, 2);
buildMLocValueMap(MInLocs, MOutLocs, TransferFunc);
EXPECT_EQ(MInLocs[0][0], LiveInRsp);
EXPECT_EQ(MInLocs[1][0], RspPHIInBlk1);
EXPECT_EQ(MInLocs[2][0], RspPHIInBlk2);
EXPECT_EQ(MInLocs[3][0], LiveInRsp);
EXPECT_EQ(MInLocs[4][0], RspDefInBlk3);
EXPECT_EQ(MOutLocs[0][0], LiveInRsp);
EXPECT_EQ(MOutLocs[1][0], LiveInRsp);
EXPECT_EQ(MOutLocs[2][0], LiveInRsp);
EXPECT_EQ(MOutLocs[3][0], RspDefInBlk3);
EXPECT_EQ(MOutLocs[4][0], RspDefInBlk3);
TransferFunc[0].clear();
TransferFunc[1].clear();
TransferFunc[2].clear();
TransferFunc[3].clear();
TransferFunc[0].insert({RaxLoc, LiveInRsp});
TransferFunc[1].insert({RspLoc, RaxPHIInBlk1});
TransferFunc[2].insert({RspLoc, RaxPHIInBlk2});
initValueArray(MInLocs, 5, 2);
initValueArray(MOutLocs, 5, 2);
buildMLocValueMap(MInLocs, MOutLocs, TransferFunc);
EXPECT_EQ(MInLocs[0][0], LiveInRsp);
EXPECT_EQ(MInLocs[1][0], LiveInRsp);
EXPECT_EQ(MInLocs[2][0], LiveInRsp);
EXPECT_EQ(MInLocs[3][0], LiveInRsp);
EXPECT_EQ(MInLocs[4][0], LiveInRsp);
EXPECT_EQ(MOutLocs[0][0], LiveInRsp);
EXPECT_EQ(MOutLocs[1][0], LiveInRsp);
EXPECT_EQ(MOutLocs[2][0], LiveInRsp);
EXPECT_EQ(MOutLocs[3][0], LiveInRsp);
EXPECT_EQ(MOutLocs[4][0], LiveInRsp);
TransferFunc[0].clear();
TransferFunc[1].clear();
TransferFunc[2].clear();
}
TEST_F(InstrRefLDVTest, MLocBadlyNestedLoops) {
setupBadlyNestedLoops();
ASSERT_TRUE(MTracker->getNumLocs() == 1);
LocIdx RspLoc(0);
Register RAX = getRegByName("RAX");
LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX);
FuncValueTable MInLocs, MOutLocs;
std::tie(MInLocs, MOutLocs) = allocValueTables(5, 2);
SmallVector<MLocTransferMap, 1> TransferFunc;
TransferFunc.resize(5);
unsigned EntryBlk = 0, Loop1Blk = 1, Loop2Blk = 2, Loop3Blk = 3;
ValueIDNum LiveInRsp(EntryBlk, 0, RspLoc);
ValueIDNum RspPHIInBlk1(Loop1Blk, 0, RspLoc);
ValueIDNum RspDefInBlk1(Loop1Blk, 1, RspLoc);
ValueIDNum RspPHIInBlk2(Loop2Blk, 0, RspLoc);
ValueIDNum RspPHIInBlk3(Loop3Blk, 0, RspLoc);
ValueIDNum RspDefInBlk3(Loop3Blk, 1, RspLoc);
ValueIDNum LiveInRax(EntryBlk, 0, RaxLoc);
ValueIDNum RaxPHIInBlk3(Loop3Blk, 0, RaxLoc);
initValueArray(MInLocs, 5, 2);
initValueArray(MOutLocs, 5, 2);
buildMLocValueMap(MInLocs, MOutLocs, TransferFunc);
EXPECT_EQ(MInLocs[0][0], LiveInRsp);
EXPECT_EQ(MInLocs[1][0], LiveInRsp);
EXPECT_EQ(MInLocs[2][0], LiveInRsp);
EXPECT_EQ(MInLocs[3][0], LiveInRsp);
EXPECT_EQ(MInLocs[4][0], LiveInRsp);
EXPECT_EQ(MOutLocs[0][0], LiveInRsp);
EXPECT_EQ(MOutLocs[1][0], LiveInRsp);
EXPECT_EQ(MOutLocs[2][0], LiveInRsp);
EXPECT_EQ(MOutLocs[3][0], LiveInRsp);
EXPECT_EQ(MOutLocs[4][0], LiveInRsp);
TransferFunc[3].insert({RspLoc, RspDefInBlk3});
initValueArray(MInLocs, 5, 2);
initValueArray(MOutLocs, 5, 2);
buildMLocValueMap(MInLocs, MOutLocs, TransferFunc);
EXPECT_EQ(MInLocs[0][0], LiveInRsp);
EXPECT_EQ(MInLocs[1][0], RspPHIInBlk1);
EXPECT_EQ(MInLocs[2][0], RspPHIInBlk2);
EXPECT_EQ(MInLocs[3][0], RspPHIInBlk3);
EXPECT_EQ(MInLocs[4][0], RspDefInBlk3);
EXPECT_EQ(MOutLocs[0][0], LiveInRsp);
EXPECT_EQ(MOutLocs[1][0], RspPHIInBlk1);
EXPECT_EQ(MOutLocs[2][0], RspPHIInBlk2);
EXPECT_EQ(MOutLocs[3][0], RspDefInBlk3);
EXPECT_EQ(MOutLocs[4][0], RspDefInBlk3);
TransferFunc[3].clear();
TransferFunc[1].insert({RspLoc, RspDefInBlk1});
initValueArray(MInLocs, 5, 2);
initValueArray(MOutLocs, 5, 2);
buildMLocValueMap(MInLocs, MOutLocs, TransferFunc);
EXPECT_EQ(MInLocs[0][0], LiveInRsp);
EXPECT_EQ(MInLocs[1][0], RspPHIInBlk1);
EXPECT_EQ(MInLocs[2][0], RspDefInBlk1);
EXPECT_EQ(MInLocs[3][0], RspDefInBlk1);
EXPECT_EQ(MInLocs[4][0], RspDefInBlk1);
EXPECT_EQ(MOutLocs[0][0], LiveInRsp);
EXPECT_EQ(MOutLocs[1][0], RspDefInBlk1);
EXPECT_EQ(MOutLocs[2][0], RspDefInBlk1);
EXPECT_EQ(MOutLocs[3][0], RspDefInBlk1);
EXPECT_EQ(MOutLocs[4][0], RspDefInBlk1);
TransferFunc[1].clear();
TransferFunc[0].insert({RaxLoc, LiveInRsp});
TransferFunc[3].insert({RspLoc, RaxPHIInBlk3});
initValueArray(MInLocs, 5, 2);
initValueArray(MOutLocs, 5, 2);
buildMLocValueMap(MInLocs, MOutLocs, TransferFunc);
EXPECT_EQ(MInLocs[0][0], LiveInRsp);
EXPECT_EQ(MInLocs[1][0], RspPHIInBlk1);
EXPECT_EQ(MInLocs[2][0], RspPHIInBlk2);
EXPECT_EQ(MInLocs[3][0], RspPHIInBlk3);
EXPECT_EQ(MInLocs[4][0], LiveInRsp);
EXPECT_EQ(MOutLocs[0][0], LiveInRsp);
EXPECT_EQ(MOutLocs[1][0], RspPHIInBlk1);
EXPECT_EQ(MOutLocs[2][0], RspPHIInBlk2);
EXPECT_EQ(MOutLocs[3][0], LiveInRsp);
EXPECT_EQ(MOutLocs[4][0], LiveInRsp);
EXPECT_EQ(MInLocs[0][1], LiveInRax);
EXPECT_EQ(MInLocs[1][1], LiveInRsp);
EXPECT_EQ(MInLocs[2][1], LiveInRsp);
EXPECT_EQ(MInLocs[3][1], LiveInRsp);
EXPECT_EQ(MInLocs[4][1], LiveInRsp);
EXPECT_EQ(MOutLocs[0][1], LiveInRsp);
EXPECT_EQ(MOutLocs[1][1], LiveInRsp);
EXPECT_EQ(MOutLocs[2][1], LiveInRsp);
EXPECT_EQ(MOutLocs[3][1], LiveInRsp);
EXPECT_EQ(MOutLocs[4][1], LiveInRsp);
}
TEST_F(InstrRefLDVTest, pickVPHILocDiamond) {
setupDiamondBlocks();
ASSERT_TRUE(MTracker->getNumLocs() == 1);
LocIdx RspLoc(0);
Register RAX = getRegByName("RAX");
LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX);
FuncValueTable MInLocs, MOutLocs;
std::tie(MInLocs, MOutLocs) = allocValueTables(4, 2);
initValueArray(MOutLocs, 4, 2);
unsigned EntryBlk = 0, Br2Blk = 2, RetBlk = 3;
ValueIDNum LiveInRsp(EntryBlk, 0, RspLoc);
ValueIDNum LiveInRax(EntryBlk, 0, RaxLoc);
ValueIDNum RspPHIInBlk2(Br2Blk, 0, RspLoc);
ValueIDNum RspPHIInBlk3(RetBlk, 0, RspLoc);
DebugVariable Var(FuncVariable, None, nullptr);
DbgValueProperties EmptyProps(EmptyExpr, false);
SmallVector<DbgValue, 32> VLiveOuts;
VLiveOuts.resize(4, DbgValue(EmptyProps, DbgValue::Undef));
InstrRefBasedLDV::LiveIdxT VLiveOutIdx;
VLiveOutIdx[MBB0] = &VLiveOuts[0];
VLiveOutIdx[MBB1] = &VLiveOuts[1];
VLiveOutIdx[MBB2] = &VLiveOuts[2];
VLiveOutIdx[MBB3] = &VLiveOuts[3];
SmallVector<const MachineBasicBlock *, 2> Preds;
for (const auto *Pred : MBB3->predecessors())
Preds.push_back(Pred);
MOutLocs[1][0] = LiveInRsp;
MOutLocs[2][0] = LiveInRax;
Optional<ValueIDNum> Result;
VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def);
VLiveOuts[2] = DbgValue(LiveInRax, EmptyProps, DbgValue::Def);
Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, MOutLocs, Preds);
EXPECT_TRUE(Result);
if (Result) {
EXPECT_EQ(*Result, RspPHIInBlk3);
}
std::swap(VLiveOuts[1], VLiveOuts[2]);
Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, MOutLocs, Preds);
EXPECT_FALSE(Result);
std::swap(VLiveOuts[1], VLiveOuts[2]);
VLiveOuts[1].Kind = DbgValue::Const;
VLiveOuts[1].MO = MachineOperand::CreateImm(0);
Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, MOutLocs, Preds);
EXPECT_FALSE(Result);
VLiveOuts[2] = VLiveOuts[1];
Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, MOutLocs, Preds);
EXPECT_FALSE(Result);
VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def);
VLiveOuts[2] = DbgValue(2, EmptyProps, DbgValue::NoVal);
Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, MOutLocs, Preds);
EXPECT_FALSE(Result);
VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def);
VLiveOuts[2] = DbgValue(2, EmptyProps, DbgValue::VPHI);
EXPECT_EQ(VLiveOuts[2].ID, ValueIDNum::EmptyValue);
Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, MOutLocs, Preds);
EXPECT_FALSE(Result);
MOutLocs[2][0] = RspPHIInBlk2;
VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def);
VLiveOuts[2] = DbgValue(2, EmptyProps, DbgValue::VPHI);
VLiveOuts[2].ID = RspPHIInBlk2; Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, MOutLocs, Preds);
EXPECT_TRUE(Result);
if (Result) {
EXPECT_EQ(*Result, RspPHIInBlk3);
}
MOutLocs[2][0] = LiveInRsp;
Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, MOutLocs, Preds);
EXPECT_FALSE(Result);
DIExpression *NewExpr =
DIExpression::prepend(EmptyExpr, DIExpression::ApplyOffset, 4);
DbgValueProperties PropsWithExpr(NewExpr, false);
VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def);
VLiveOuts[2] = DbgValue(LiveInRsp, PropsWithExpr, DbgValue::Def);
Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, MOutLocs, Preds);
EXPECT_FALSE(Result);
DbgValueProperties PropsWithIndirect(EmptyExpr, true);
VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def);
VLiveOuts[2] = DbgValue(LiveInRsp, PropsWithIndirect, DbgValue::Def);
Result = pickVPHILoc(*MBB3, Var, VLiveOutIdx, MOutLocs, Preds);
EXPECT_FALSE(Result);
}
TEST_F(InstrRefLDVTest, pickVPHILocLoops) {
setupSimpleLoop();
ASSERT_TRUE(MTracker->getNumLocs() == 1);
LocIdx RspLoc(0);
Register RAX = getRegByName("RAX");
LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX);
FuncValueTable MInLocs, MOutLocs;
std::tie(MInLocs, MOutLocs) = allocValueTables(3, 2);
initValueArray(MOutLocs, 3, 2);
unsigned EntryBlk = 0, LoopBlk = 1;
ValueIDNum LiveInRsp(EntryBlk, 0, RspLoc);
ValueIDNum LiveInRax(EntryBlk, 0, RaxLoc);
ValueIDNum RspPHIInBlk1(LoopBlk, 0, RspLoc);
ValueIDNum RaxPHIInBlk1(LoopBlk, 0, RaxLoc);
DebugVariable Var(FuncVariable, None, nullptr);
DbgValueProperties EmptyProps(EmptyExpr, false);
SmallVector<DbgValue, 32> VLiveOuts;
VLiveOuts.resize(3, DbgValue(EmptyProps, DbgValue::Undef));
InstrRefBasedLDV::LiveIdxT VLiveOutIdx;
VLiveOutIdx[MBB0] = &VLiveOuts[0];
VLiveOutIdx[MBB1] = &VLiveOuts[1];
VLiveOutIdx[MBB2] = &VLiveOuts[2];
SmallVector<const MachineBasicBlock *, 2> Preds;
for (const auto *Pred : MBB1->predecessors())
Preds.push_back(Pred);
MOutLocs[0][0] = LiveInRsp;
MOutLocs[1][0] = LiveInRax;
Optional<ValueIDNum> Result;
VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def);
VLiveOuts[1] = DbgValue(LiveInRax, EmptyProps, DbgValue::Def);
Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, MOutLocs, Preds);
EXPECT_TRUE(Result);
if (Result) {
EXPECT_EQ(*Result, RspPHIInBlk1);
}
MOutLocs[1][0] = LiveInRsp;
Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, MOutLocs, Preds);
EXPECT_FALSE(Result);
MOutLocs[0][0] = LiveInRsp;
MOutLocs[0][1] = LiveInRsp;
MOutLocs[1][0] = RaxPHIInBlk1;
MOutLocs[1][1] = RaxPHIInBlk1;
VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def);
VLiveOuts[1] = DbgValue(1, EmptyProps, DbgValue::VPHI);
Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, MOutLocs, Preds);
EXPECT_TRUE(Result);
if (Result) {
EXPECT_EQ(*Result, RaxPHIInBlk1);
}
MOutLocs[1][1] = LiveInRax;
Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, MOutLocs, Preds);
EXPECT_FALSE(Result);
MOutLocs[1][1] = RaxPHIInBlk1;
VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def);
VLiveOuts[1] = DbgValue(0, EmptyProps, DbgValue::VPHI);
Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, MOutLocs, Preds);
EXPECT_FALSE(Result);
}
TEST_F(InstrRefLDVTest, pickVPHILocBadlyNestedLoops) {
setupBadlyNestedLoops();
ASSERT_TRUE(MTracker->getNumLocs() == 1);
LocIdx RspLoc(0);
Register RAX = getRegByName("RAX");
LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX);
Register RBX = getRegByName("RBX");
LocIdx RbxLoc = MTracker->lookupOrTrackRegister(RBX);
FuncValueTable MInLocs, MOutLocs;
std::tie(MInLocs, MOutLocs) = allocValueTables(5, 3);
initValueArray(MOutLocs, 5, 3);
unsigned EntryBlk = 0, Loop1Blk = 1;
ValueIDNum LiveInRsp(EntryBlk, 0, RspLoc);
ValueIDNum LiveInRax(EntryBlk, 0, RaxLoc);
ValueIDNum LiveInRbx(EntryBlk, 0, RbxLoc);
ValueIDNum RspPHIInBlk1(Loop1Blk, 0, RspLoc);
ValueIDNum RaxPHIInBlk1(Loop1Blk, 0, RaxLoc);
ValueIDNum RbxPHIInBlk1(Loop1Blk, 0, RbxLoc);
DebugVariable Var(FuncVariable, None, nullptr);
DbgValueProperties EmptyProps(EmptyExpr, false);
SmallVector<DbgValue, 32> VLiveOuts;
VLiveOuts.resize(5, DbgValue(EmptyProps, DbgValue::Undef));
InstrRefBasedLDV::LiveIdxT VLiveOutIdx;
VLiveOutIdx[MBB0] = &VLiveOuts[0];
VLiveOutIdx[MBB1] = &VLiveOuts[1];
VLiveOutIdx[MBB2] = &VLiveOuts[2];
VLiveOutIdx[MBB3] = &VLiveOuts[3];
VLiveOutIdx[MBB4] = &VLiveOuts[4];
SmallVector<const MachineBasicBlock *, 2> Preds;
for (const auto *Pred : MBB1->predecessors())
Preds.push_back(Pred);
MOutLocs[0][0] = LiveInRsp;
MOutLocs[1][0] = LiveInRax;
MOutLocs[2][0] = LiveInRbx;
Optional<ValueIDNum> Result;
VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def);
VLiveOuts[1] = DbgValue(LiveInRax, EmptyProps, DbgValue::Def);
VLiveOuts[2] = DbgValue(LiveInRbx, EmptyProps, DbgValue::Def);
Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, MOutLocs, Preds);
EXPECT_TRUE(Result);
if (Result) {
EXPECT_EQ(*Result, RspPHIInBlk1);
}
MOutLocs[0][0] = LiveInRax;
MOutLocs[1][0] = LiveInRbx;
MOutLocs[2][0] = LiveInRsp;
Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, MOutLocs, Preds);
EXPECT_FALSE(Result);
MOutLocs[0][0] = LiveInRsp;
MOutLocs[1][0] = LiveInRax;
MOutLocs[2][0] = LiveInRbx;
MOutLocs[1][0] = RspPHIInBlk1;
Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, MOutLocs, Preds);
EXPECT_FALSE(Result);
VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def);
VLiveOuts[1] = DbgValue(1, EmptyProps, DbgValue::VPHI);
VLiveOuts[2] = DbgValue(LiveInRbx, EmptyProps, DbgValue::Def);
Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, MOutLocs, Preds);
EXPECT_TRUE(Result);
if (Result) {
EXPECT_EQ(*Result, RspPHIInBlk1);
}
MOutLocs[2][0] = RspPHIInBlk1;
VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def);
VLiveOuts[1] = DbgValue(1, EmptyProps, DbgValue::VPHI);
VLiveOuts[2] = DbgValue(1, EmptyProps, DbgValue::VPHI);
Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, MOutLocs, Preds);
EXPECT_TRUE(Result);
if (Result) {
EXPECT_EQ(*Result, RspPHIInBlk1);
}
MOutLocs[2][0] = RaxPHIInBlk1;
Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, MOutLocs, Preds);
EXPECT_FALSE(Result);
MOutLocs[0][0] = LiveInRsp;
MOutLocs[1][0] = RspPHIInBlk1;
MOutLocs[2][0] = LiveInRsp;
MOutLocs[2][1] = RspPHIInBlk1;
Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, MOutLocs, Preds);
EXPECT_FALSE(Result);
MOutLocs[0][2] = LiveInRsp;
MOutLocs[1][0] = RspPHIInBlk1;
MOutLocs[1][1] = RaxPHIInBlk1;
MOutLocs[1][2] = RbxPHIInBlk1;
MOutLocs[2][0] = LiveInRsp;
MOutLocs[2][1] = RspPHIInBlk1;
MOutLocs[2][2] = RbxPHIInBlk1;
Result = pickVPHILoc(*MBB1, Var, VLiveOutIdx, MOutLocs, Preds);
EXPECT_TRUE(Result);
if (Result) {
EXPECT_EQ(*Result, RbxPHIInBlk1);
}
}
TEST_F(InstrRefLDVTest, vlocJoinDiamond) {
setupDiamondBlocks();
ASSERT_TRUE(MTracker->getNumLocs() == 1);
LocIdx RspLoc(0);
Register RAX = getRegByName("RAX");
LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX);
unsigned EntryBlk = 0, Br2Blk = 2, RetBlk = 3;
ValueIDNum LiveInRsp(EntryBlk, 0, RspLoc);
ValueIDNum LiveInRax(EntryBlk, 0, RaxLoc);
ValueIDNum RspPHIInBlkBr2Blk(Br2Blk, 0, RspLoc);
ValueIDNum RspPHIInBlkRetBlk(RetBlk, 0, RspLoc);
DebugVariable Var(FuncVariable, None, nullptr);
DbgValueProperties EmptyProps(EmptyExpr, false);
SmallVector<DbgValue, 32> VLiveOuts;
VLiveOuts.resize(4, DbgValue(EmptyProps, DbgValue::Undef));
InstrRefBasedLDV::LiveIdxT VLiveOutIdx;
VLiveOutIdx[MBB0] = &VLiveOuts[0];
VLiveOutIdx[MBB1] = &VLiveOuts[1];
VLiveOutIdx[MBB2] = &VLiveOuts[2];
VLiveOutIdx[MBB3] = &VLiveOuts[3];
SmallPtrSet<const MachineBasicBlock *, 8> AllBlocks;
AllBlocks.insert(MBB0);
AllBlocks.insert(MBB1);
AllBlocks.insert(MBB2);
AllBlocks.insert(MBB3);
SmallVector<const MachineBasicBlock *, 2> Preds;
for (const auto *Pred : MBB3->predecessors())
Preds.push_back(Pred);
SmallSet<DebugVariable, 4> AllVars;
AllVars.insert(Var);
DbgValue JoinedLoc = DbgValue(3, EmptyProps, DbgValue::NoVal);
VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def);
VLiveOuts[2] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def);
bool Result = vlocJoin(*MBB3, VLiveOutIdx, AllBlocks, JoinedLoc);
EXPECT_TRUE(Result); EXPECT_EQ(JoinedLoc.Kind, DbgValue::Def);
EXPECT_EQ(JoinedLoc.ID, LiveInRsp);
Result = vlocJoin(*MBB3, VLiveOutIdx, AllBlocks, JoinedLoc);
EXPECT_FALSE(Result);
VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def);
VLiveOuts[2] = DbgValue(LiveInRax, EmptyProps, DbgValue::Def);
JoinedLoc = DbgValue(3, EmptyProps, DbgValue::NoVal);
Result = vlocJoin(*MBB3, VLiveOutIdx, AllBlocks, JoinedLoc);
EXPECT_TRUE(Result);
EXPECT_EQ(JoinedLoc.Kind, DbgValue::Def);
EXPECT_EQ(JoinedLoc.ID, LiveInRax);
JoinedLoc = DbgValue(3, EmptyProps, DbgValue::VPHI);
Result = vlocJoin(*MBB3, VLiveOutIdx, AllBlocks, JoinedLoc);
EXPECT_FALSE(Result);
EXPECT_EQ(JoinedLoc.Kind, DbgValue::VPHI);
EXPECT_EQ(JoinedLoc.ID, ValueIDNum::EmptyValue);
EXPECT_EQ(JoinedLoc.BlockNo, 3);
VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def);
VLiveOuts[2] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def);
JoinedLoc = DbgValue(3, EmptyProps, DbgValue::VPHI);
Result = vlocJoin(*MBB3, VLiveOutIdx, AllBlocks, JoinedLoc);
EXPECT_TRUE(Result);
EXPECT_EQ(JoinedLoc.Kind, DbgValue::Def);
EXPECT_EQ(JoinedLoc.ID, LiveInRsp);
VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def);
VLiveOuts[2] = DbgValue(LiveInRax, EmptyProps, DbgValue::Def);
JoinedLoc = DbgValue(2, EmptyProps, DbgValue::VPHI);
Result = vlocJoin(*MBB3, VLiveOutIdx, AllBlocks, JoinedLoc);
EXPECT_TRUE(Result);
EXPECT_EQ(JoinedLoc.Kind, DbgValue::Def);
EXPECT_EQ(JoinedLoc.ID, LiveInRax);
VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def);
VLiveOuts[2] = DbgValue(0, EmptyProps, DbgValue::VPHI);
JoinedLoc = DbgValue(2, EmptyProps, DbgValue::VPHI);
Result = vlocJoin(*MBB3, VLiveOutIdx, AllBlocks, JoinedLoc);
EXPECT_TRUE(Result);
EXPECT_EQ(JoinedLoc.Kind, DbgValue::VPHI);
EXPECT_EQ(JoinedLoc.BlockNo, 0);
DbgValueProperties PropsWithIndirect(EmptyExpr, true);
VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def);
VLiveOuts[2] = DbgValue(LiveInRsp, PropsWithIndirect, DbgValue::Def);
JoinedLoc = DbgValue(3, EmptyProps, DbgValue::VPHI);
Result = vlocJoin(*MBB3, VLiveOutIdx, AllBlocks, JoinedLoc);
EXPECT_FALSE(Result);
EXPECT_EQ(JoinedLoc.Kind, DbgValue::VPHI);
EXPECT_EQ(JoinedLoc.BlockNo, 3);
VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def);
VLiveOuts[2] = DbgValue(LiveInRsp, PropsWithIndirect, DbgValue::Def);
JoinedLoc = DbgValue(2, EmptyProps, DbgValue::VPHI);
Result = vlocJoin(*MBB3, VLiveOutIdx, AllBlocks, JoinedLoc);
EXPECT_TRUE(Result);
EXPECT_EQ(JoinedLoc.Kind, DbgValue::Def);
EXPECT_EQ(JoinedLoc.ID, LiveInRsp);
EXPECT_EQ(JoinedLoc.Properties, PropsWithIndirect);
DIExpression *NewExpr =
DIExpression::prepend(EmptyExpr, DIExpression::ApplyOffset, 4);
DbgValueProperties PropsWithExpr(NewExpr, false);
VLiveOuts[1] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def);
VLiveOuts[2] = DbgValue(LiveInRsp, PropsWithExpr, DbgValue::Def);
JoinedLoc = DbgValue(3, EmptyProps, DbgValue::VPHI);
Result = vlocJoin(*MBB3, VLiveOutIdx, AllBlocks, JoinedLoc);
EXPECT_FALSE(Result);
}
TEST_F(InstrRefLDVTest, vlocJoinLoops) {
setupSimpleLoop();
ASSERT_TRUE(MTracker->getNumLocs() == 1);
LocIdx RspLoc(0);
Register RAX = getRegByName("RAX");
LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX);
unsigned EntryBlk = 0, LoopBlk = 1;
ValueIDNum LiveInRsp(EntryBlk, 0, RspLoc);
ValueIDNum LiveInRax(EntryBlk, 0, RaxLoc);
ValueIDNum RspPHIInBlk1(LoopBlk, 0, RspLoc);
DebugVariable Var(FuncVariable, None, nullptr);
DbgValueProperties EmptyProps(EmptyExpr, false);
SmallVector<DbgValue, 32> VLiveOuts;
VLiveOuts.resize(3, DbgValue(EmptyProps, DbgValue::Undef));
InstrRefBasedLDV::LiveIdxT VLiveOutIdx;
VLiveOutIdx[MBB0] = &VLiveOuts[0];
VLiveOutIdx[MBB1] = &VLiveOuts[1];
VLiveOutIdx[MBB2] = &VLiveOuts[2];
SmallPtrSet<const MachineBasicBlock *, 8> AllBlocks;
AllBlocks.insert(MBB0);
AllBlocks.insert(MBB1);
AllBlocks.insert(MBB2);
SmallVector<const MachineBasicBlock *, 2> Preds;
for (const auto *Pred : MBB1->predecessors())
Preds.push_back(Pred);
SmallSet<DebugVariable, 4> AllVars;
AllVars.insert(Var);
VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def);
VLiveOuts[1] = DbgValue(LiveInRax, EmptyProps, DbgValue::Def);
DbgValue JoinedLoc = DbgValue(LiveInRax, EmptyProps, DbgValue::Def);
bool Result = vlocJoin(*MBB1, VLiveOutIdx, AllBlocks, JoinedLoc);
EXPECT_TRUE(Result);
EXPECT_EQ(JoinedLoc.Kind, DbgValue::Def);
EXPECT_EQ(JoinedLoc.ID, LiveInRsp);
VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def);
VLiveOuts[1] = DbgValue(LiveInRax, EmptyProps, DbgValue::Def);
JoinedLoc = DbgValue(1, EmptyProps, DbgValue::VPHI);
Result = vlocJoin(*MBB1, VLiveOutIdx, AllBlocks, JoinedLoc);
EXPECT_FALSE(Result);
EXPECT_EQ(JoinedLoc.Kind, DbgValue::VPHI);
EXPECT_EQ(JoinedLoc.BlockNo, 1);
VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def);
VLiveOuts[1] = DbgValue(1, EmptyProps, DbgValue::VPHI);
JoinedLoc = DbgValue(1, EmptyProps, DbgValue::VPHI);
Result = vlocJoin(*MBB1, VLiveOutIdx, AllBlocks, JoinedLoc);
EXPECT_TRUE(Result);
EXPECT_EQ(JoinedLoc.Kind, DbgValue::Def);
EXPECT_EQ(JoinedLoc.ID, LiveInRsp);
DIExpression *NewExpr =
DIExpression::prepend(EmptyExpr, DIExpression::ApplyOffset, 4);
DbgValueProperties PropsWithExpr(NewExpr, false);
VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def);
VLiveOuts[1] = DbgValue(1, PropsWithExpr, DbgValue::VPHI);
JoinedLoc = DbgValue(1, EmptyProps, DbgValue::VPHI);
Result = vlocJoin(*MBB1, VLiveOutIdx, AllBlocks, JoinedLoc);
EXPECT_FALSE(Result);
EXPECT_EQ(JoinedLoc.Kind, DbgValue::VPHI);
EXPECT_EQ(JoinedLoc.BlockNo, 1);
VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def);
VLiveOuts[1] = DbgValue(0, EmptyProps, DbgValue::VPHI);
JoinedLoc = DbgValue(1, EmptyProps, DbgValue::VPHI);
Result = vlocJoin(*MBB1, VLiveOutIdx, AllBlocks, JoinedLoc);
EXPECT_FALSE(Result);
EXPECT_EQ(JoinedLoc.Kind, DbgValue::VPHI);
EXPECT_EQ(JoinedLoc.BlockNo, 1);
}
TEST_F(InstrRefLDVTest, vlocJoinBadlyNestedLoops) {
setupBadlyNestedLoops();
ASSERT_TRUE(MTracker->getNumLocs() == 1);
LocIdx RspLoc(0);
Register RAX = getRegByName("RAX");
LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX);
Register RBX = getRegByName("RBX");
LocIdx RbxLoc = MTracker->lookupOrTrackRegister(RBX);
unsigned EntryBlk = 0;
ValueIDNum LiveInRsp(EntryBlk, 0, RspLoc);
ValueIDNum LiveInRax(EntryBlk, 0, RaxLoc);
ValueIDNum LiveInRbx(EntryBlk, 0, RbxLoc);
DebugVariable Var(FuncVariable, None, nullptr);
DbgValueProperties EmptyProps(EmptyExpr, false);
SmallVector<DbgValue, 32> VLiveOuts;
VLiveOuts.resize(5, DbgValue(EmptyProps, DbgValue::Undef));
InstrRefBasedLDV::LiveIdxT VLiveOutIdx;
VLiveOutIdx[MBB0] = &VLiveOuts[0];
VLiveOutIdx[MBB1] = &VLiveOuts[1];
VLiveOutIdx[MBB2] = &VLiveOuts[2];
VLiveOutIdx[MBB3] = &VLiveOuts[3];
VLiveOutIdx[MBB4] = &VLiveOuts[4];
SmallPtrSet<const MachineBasicBlock *, 8> AllBlocks;
AllBlocks.insert(MBB0);
AllBlocks.insert(MBB1);
AllBlocks.insert(MBB2);
AllBlocks.insert(MBB3);
AllBlocks.insert(MBB4);
SmallVector<const MachineBasicBlock *, 3> Preds;
for (const auto *Pred : MBB1->predecessors())
Preds.push_back(Pred);
SmallSet<DebugVariable, 4> AllVars;
AllVars.insert(Var);
VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def);
VLiveOuts[1] = DbgValue(LiveInRax, EmptyProps, DbgValue::Def);
VLiveOuts[2] = DbgValue(LiveInRbx, EmptyProps, DbgValue::Def);
DbgValue JoinedLoc = DbgValue(1, EmptyProps, DbgValue::VPHI);
bool Result = vlocJoin(*MBB1, VLiveOutIdx, AllBlocks, JoinedLoc);
EXPECT_FALSE(Result);
EXPECT_EQ(JoinedLoc.Kind, DbgValue::VPHI);
EXPECT_EQ(JoinedLoc.BlockNo, 1);
VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def);
VLiveOuts[1] = DbgValue(1, EmptyProps, DbgValue::VPHI);
VLiveOuts[2] = DbgValue(1, EmptyProps, DbgValue::VPHI);
JoinedLoc = DbgValue(1, EmptyProps, DbgValue::VPHI);
Result = vlocJoin(*MBB1, VLiveOutIdx, AllBlocks, JoinedLoc);
EXPECT_TRUE(Result);
EXPECT_EQ(JoinedLoc.Kind, DbgValue::Def);
EXPECT_EQ(JoinedLoc.ID, LiveInRsp);
DbgValueProperties PropsWithIndirect(EmptyExpr, true);
VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def);
VLiveOuts[1] = DbgValue(1, EmptyProps, DbgValue::VPHI);
VLiveOuts[2] = DbgValue(1, PropsWithIndirect, DbgValue::VPHI);
JoinedLoc = DbgValue(1, EmptyProps, DbgValue::VPHI);
Result = vlocJoin(*MBB1, VLiveOutIdx, AllBlocks, JoinedLoc);
EXPECT_FALSE(Result);
EXPECT_EQ(JoinedLoc.Kind, DbgValue::VPHI);
EXPECT_EQ(JoinedLoc.BlockNo, 1);
VLiveOuts[0] = DbgValue(LiveInRsp, EmptyProps, DbgValue::Def);
VLiveOuts[1] = DbgValue(1, EmptyProps, DbgValue::VPHI);
VLiveOuts[2] = DbgValue(2, EmptyProps, DbgValue::VPHI);
JoinedLoc = DbgValue(1, EmptyProps, DbgValue::VPHI);
Result = vlocJoin(*MBB1, VLiveOutIdx, AllBlocks, JoinedLoc);
EXPECT_FALSE(Result);
EXPECT_EQ(JoinedLoc.Kind, DbgValue::VPHI);
EXPECT_EQ(JoinedLoc.BlockNo, 1);
}
TEST_F(InstrRefLDVTest, VLocSingleBlock) {
setupSingleBlock();
ASSERT_TRUE(MTracker->getNumLocs() == 1);
LocIdx RspLoc(0);
FuncValueTable MInLocs, MOutLocs;
std::tie(MInLocs, MOutLocs) = allocValueTables(1, 2);
ValueIDNum LiveInRsp = ValueIDNum(0, 0, RspLoc);
MInLocs[0][0] = MOutLocs[0][0] = LiveInRsp;
DebugVariable Var(FuncVariable, None, nullptr);
DbgValueProperties EmptyProps(EmptyExpr, false);
SmallSet<DebugVariable, 4> AllVars;
AllVars.insert(Var);
SmallPtrSet<MachineBasicBlock *, 4> AssignBlocks;
AssignBlocks.insert(MBB0);
SmallVector<VLocTracker, 1> VLocs;
VLocs.resize(1, VLocTracker(Overlaps, EmptyExpr));
InstrRefBasedLDV::LiveInsT Output;
buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output,
MOutLocs, MInLocs, VLocs);
EXPECT_EQ(Output.size(), 0ul);
VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)});
buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output,
MOutLocs, MInLocs, VLocs);
EXPECT_EQ(Output.size(), 0ul);
}
TEST_F(InstrRefLDVTest, VLocDiamondBlocks) {
setupDiamondBlocks();
ASSERT_TRUE(MTracker->getNumLocs() == 1);
LocIdx RspLoc(0);
Register RAX = getRegByName("RAX");
LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX);
unsigned EntryBlk = 0, RetBlk = 3;
ValueIDNum LiveInRsp = ValueIDNum(EntryBlk, 0, RspLoc);
ValueIDNum LiveInRax = ValueIDNum(EntryBlk, 0, RaxLoc);
ValueIDNum RspPHIInBlk3 = ValueIDNum(RetBlk, 0, RspLoc);
FuncValueTable MInLocs, MOutLocs;
std::tie(MInLocs, MOutLocs) = allocValueTables(4, 2);
initValueArray(MInLocs, 4, 2);
initValueArray(MOutLocs, 4, 2);
DebugVariable Var(FuncVariable, None, nullptr);
DbgValueProperties EmptyProps(EmptyExpr, false);
SmallSet<DebugVariable, 4> AllVars;
AllVars.insert(Var);
SmallPtrSet<MachineBasicBlock *, 4> AssignBlocks;
AssignBlocks.insert(MBB0);
AssignBlocks.insert(MBB1);
AssignBlocks.insert(MBB2);
AssignBlocks.insert(MBB3);
SmallVector<VLocTracker, 1> VLocs;
VLocs.resize(4, VLocTracker(Overlaps, EmptyExpr));
InstrRefBasedLDV::LiveInsT Output;
for (unsigned int I = 0; I < 4; ++I) {
MInLocs[I][0] = MInLocs[I][1] = LiveInRsp;
MOutLocs[I][0] = MOutLocs[I][1] = LiveInRsp;
}
auto ClearOutputs = [&]() {
for (auto &Elem : Output)
Elem.clear();
};
Output.resize(4);
buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output,
MOutLocs, MInLocs, VLocs);
EXPECT_EQ(Output[0].size(), 0ul);
EXPECT_EQ(Output[1].size(), 0ul);
EXPECT_EQ(Output[2].size(), 0ul);
EXPECT_EQ(Output[3].size(), 0ul);
VLocs[3].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)});
buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output,
MOutLocs, MInLocs, VLocs);
EXPECT_EQ(Output[0].size(), 0ul);
EXPECT_EQ(Output[1].size(), 0ul);
EXPECT_EQ(Output[2].size(), 0ul);
EXPECT_EQ(Output[3].size(), 0ul);
ClearOutputs();
VLocs[3].Vars.clear();
VLocs[2].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)});
buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output,
MOutLocs, MInLocs, VLocs);
EXPECT_EQ(Output[0].size(), 0ul);
EXPECT_EQ(Output[1].size(), 0ul);
EXPECT_EQ(Output[2].size(), 0ul);
EXPECT_EQ(Output[3].size(), 0ul);
VLocs[2].Vars.clear();
ClearOutputs();
VLocs[1].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)});
buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output,
MOutLocs, MInLocs, VLocs);
EXPECT_EQ(Output[0].size(), 0ul);
EXPECT_EQ(Output[1].size(), 0ul);
EXPECT_EQ(Output[2].size(), 0ul);
EXPECT_EQ(Output[3].size(), 0ul);
VLocs[1].Vars.clear();
ClearOutputs();
VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)});
buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output,
MOutLocs, MInLocs, VLocs);
EXPECT_EQ(Output[0].size(), 0ul);
ASSERT_EQ(Output[1].size(), 1ul);
ASSERT_EQ(Output[2].size(), 1ul);
ASSERT_EQ(Output[3].size(), 1ul);
EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[1][0].second.ID, LiveInRsp);
EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[2][0].second.ID, LiveInRsp);
EXPECT_EQ(Output[3][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[3][0].second.ID, LiveInRsp);
ClearOutputs();
VLocs[0].Vars.clear();
VLocs[0].Vars.insert({Var, DbgValue(LiveInRax, EmptyProps, DbgValue::Def)});
buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output,
MOutLocs, MInLocs, VLocs);
EXPECT_EQ(Output[0].size(), 0ul);
ASSERT_EQ(Output[1].size(), 1ul);
ASSERT_EQ(Output[2].size(), 1ul);
ASSERT_EQ(Output[3].size(), 1ul);
EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[1][0].second.ID, LiveInRax);
EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[2][0].second.ID, LiveInRax);
EXPECT_EQ(Output[3][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[3][0].second.ID, LiveInRax);
ClearOutputs();
VLocs[0].Vars.clear();
VLocs[1].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)});
VLocs[2].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)});
buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output,
MOutLocs, MInLocs, VLocs);
EXPECT_EQ(Output[0].size(), 0ul);
EXPECT_EQ(Output[1].size(), 0ul);
EXPECT_EQ(Output[2].size(), 0ul);
ASSERT_EQ(Output[3].size(), 1ul);
EXPECT_EQ(Output[3][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[3][0].second.ID, LiveInRsp);
ClearOutputs();
VLocs[1].Vars.clear();
VLocs[2].Vars.clear();
VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)});
VLocs[1].Vars.insert({Var, DbgValue(EmptyProps, DbgValue::Undef)});
buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output,
MOutLocs, MInLocs, VLocs);
EXPECT_EQ(Output[0].size(), 0ul);
ASSERT_EQ(Output[1].size(), 1ul);
ASSERT_EQ(Output[2].size(), 1ul);
EXPECT_EQ(Output[3].size(), 0ul);
EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[1][0].second.ID, LiveInRsp);
EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[2][0].second.ID, LiveInRsp);
ClearOutputs();
VLocs[0].Vars.clear();
VLocs[1].Vars.clear();
VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)});
VLocs[1].Vars.insert({Var, DbgValue(LiveInRax, EmptyProps, DbgValue::Def)});
buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output,
MOutLocs, MInLocs, VLocs);
EXPECT_EQ(Output[0].size(), 0ul);
ASSERT_EQ(Output[1].size(), 1ul);
ASSERT_EQ(Output[2].size(), 1ul);
EXPECT_EQ(Output[3].size(), 0ul);
EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[1][0].second.ID, LiveInRsp);
EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[2][0].second.ID, LiveInRsp);
ClearOutputs();
VLocs[0].Vars.clear();
VLocs[1].Vars.clear();
MOutLocs[1][0] = LiveInRax;
VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)});
VLocs[1].Vars.insert({Var, DbgValue(LiveInRax, EmptyProps, DbgValue::Def)});
buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output,
MOutLocs, MInLocs, VLocs);
EXPECT_EQ(Output[0].size(), 0ul);
ASSERT_EQ(Output[1].size(), 1ul);
ASSERT_EQ(Output[2].size(), 1ul);
ASSERT_EQ(Output[3].size(), 1ul);
EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[1][0].second.ID, LiveInRsp);
EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[2][0].second.ID, LiveInRsp);
EXPECT_EQ(Output[3][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[3][0].second.ID, RspPHIInBlk3);
ClearOutputs();
VLocs[0].Vars.clear();
VLocs[1].Vars.clear();
}
TEST_F(InstrRefLDVTest, VLocSimpleLoop) {
setupSimpleLoop();
ASSERT_TRUE(MTracker->getNumLocs() == 1);
LocIdx RspLoc(0);
Register RAX = getRegByName("RAX");
LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX);
unsigned EntryBlk = 0, LoopBlk = 1;
ValueIDNum LiveInRsp = ValueIDNum(EntryBlk, 0, RspLoc);
ValueIDNum LiveInRax = ValueIDNum(EntryBlk, 0, RaxLoc);
ValueIDNum RspPHIInBlk1 = ValueIDNum(LoopBlk, 0, RspLoc);
ValueIDNum RspDefInBlk1 = ValueIDNum(LoopBlk, 1, RspLoc);
ValueIDNum RaxPHIInBlk1 = ValueIDNum(LoopBlk, 0, RaxLoc);
FuncValueTable MInLocs, MOutLocs;
std::tie(MInLocs, MOutLocs) = allocValueTables(3, 2);
initValueArray(MInLocs, 3, 2);
initValueArray(MOutLocs, 3, 2);
DebugVariable Var(FuncVariable, None, nullptr);
DbgValueProperties EmptyProps(EmptyExpr, false);
SmallSet<DebugVariable, 4> AllVars;
AllVars.insert(Var);
SmallPtrSet<MachineBasicBlock *, 4> AssignBlocks;
AssignBlocks.insert(MBB0);
AssignBlocks.insert(MBB1);
AssignBlocks.insert(MBB2);
SmallVector<VLocTracker, 3> VLocs;
VLocs.resize(3, VLocTracker(Overlaps, EmptyExpr));
InstrRefBasedLDV::LiveInsT Output;
for (unsigned int I = 0; I < 3; ++I) {
MInLocs[I][0] = MInLocs[I][1] = LiveInRsp;
MOutLocs[I][0] = MOutLocs[I][1] = LiveInRsp;
}
auto ClearOutputs = [&]() {
for (auto &Elem : Output)
Elem.clear();
};
Output.resize(3);
VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)});
buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output,
MOutLocs, MInLocs, VLocs);
EXPECT_EQ(Output[0].size(), 0ul);
ASSERT_EQ(Output[1].size(), 1ul);
ASSERT_EQ(Output[2].size(), 1ul);
EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[1][0].second.ID, LiveInRsp);
EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[2][0].second.ID, LiveInRsp);
ClearOutputs();
VLocs[0].Vars.clear();
VLocs[1].Vars.clear();
VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)});
VLocs[1].Vars.insert({Var, DbgValue(EmptyProps, DbgValue::Undef)});
buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output,
MOutLocs, MInLocs, VLocs);
EXPECT_EQ(Output[0].size(), 0ul);
EXPECT_EQ(Output[1].size(), 0ul);
EXPECT_EQ(Output[2].size(), 0ul);
ClearOutputs();
VLocs[0].Vars.clear();
VLocs[1].Vars.clear();
VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)});
VLocs[1].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)});
buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output,
MOutLocs, MInLocs, VLocs);
EXPECT_EQ(Output[0].size(), 0ul);
ASSERT_EQ(Output[1].size(), 1ul);
ASSERT_EQ(Output[2].size(), 1ul);
EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[1][0].second.ID, LiveInRsp);
EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[2][0].second.ID, LiveInRsp);
ClearOutputs();
VLocs[0].Vars.clear();
VLocs[1].Vars.clear();
VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)});
VLocs[1].Vars.insert({Var, DbgValue(LiveInRax, EmptyProps, DbgValue::Def)});
buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output,
MOutLocs, MInLocs, VLocs);
EXPECT_EQ(Output[0].size(), 0ul);
EXPECT_EQ(Output[1].size(), 0ul);
ASSERT_EQ(Output[2].size(), 1ul);
EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[2][0].second.ID, LiveInRax);
ClearOutputs();
VLocs[0].Vars.clear();
VLocs[1].Vars.clear();
MInLocs[1][0] = RspPHIInBlk1;
MOutLocs[1][0] = RspDefInBlk1;
VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)});
VLocs[1].Vars.insert({Var, DbgValue(LiveInRax, EmptyProps, DbgValue::Def)});
buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output,
MOutLocs, MInLocs, VLocs);
EXPECT_EQ(Output[0].size(), 0ul);
EXPECT_EQ(Output[1].size(), 0ul);
ASSERT_EQ(Output[2].size(), 1ul);
EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[2][0].second.ID, LiveInRax);
ClearOutputs();
VLocs[0].Vars.clear();
VLocs[1].Vars.clear();
MInLocs[1][0] = RspPHIInBlk1;
MOutLocs[1][0] = RspDefInBlk1;
VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)});
VLocs[1].Vars.insert({Var, DbgValue(RspDefInBlk1, EmptyProps, DbgValue::Def)});
buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output,
MOutLocs, MInLocs, VLocs);
EXPECT_EQ(Output[0].size(), 0ul);
ASSERT_EQ(Output[1].size(), 1ul);
ASSERT_EQ(Output[2].size(), 1ul);
EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[1][0].second.ID, RspPHIInBlk1);
EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[2][0].second.ID, RspDefInBlk1);
ClearOutputs();
VLocs[0].Vars.clear();
VLocs[1].Vars.clear();
MInLocs[1][0] = LiveInRsp;
MOutLocs[1][0] = LiveInRsp;
MInLocs[1][1] = RaxPHIInBlk1;
MOutLocs[1][1] = RspDefInBlk1;
VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)});
VLocs[1].Vars.insert({Var, DbgValue(RspDefInBlk1, EmptyProps, DbgValue::Def)});
buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output,
MOutLocs, MInLocs, VLocs);
EXPECT_EQ(Output[0].size(), 0ul);
ASSERT_EQ(Output[1].size(), 1ul);
ASSERT_EQ(Output[2].size(), 1ul);
EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[1][0].second.ID, RaxPHIInBlk1);
EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[2][0].second.ID, RspDefInBlk1);
ClearOutputs();
VLocs[0].Vars.clear();
VLocs[1].Vars.clear();
MInLocs[1][0] = RaxPHIInBlk1;
MOutLocs[1][0] = RspDefInBlk1;
MInLocs[1][1] = RaxPHIInBlk1;
MOutLocs[1][1] = RspDefInBlk1;
VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)});
VLocs[1].Vars.insert({Var, DbgValue(RspDefInBlk1, EmptyProps, DbgValue::Def)});
buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output,
MOutLocs, MInLocs, VLocs);
EXPECT_EQ(Output[0].size(), 0ul);
ASSERT_EQ(Output[1].size(), 1ul);
ASSERT_EQ(Output[2].size(), 1ul);
EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[1][0].second.ID, RspPHIInBlk1);
EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[2][0].second.ID, RspDefInBlk1);
ClearOutputs();
VLocs[0].Vars.clear();
VLocs[1].Vars.clear();
MInLocs[1][0] = RspPHIInBlk1;
MOutLocs[1][0] = RspPHIInBlk1;
MInLocs[1][1] = LiveInRax;
MOutLocs[1][1] = LiveInRax;
VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)});
VLocs[1].Vars.insert({Var, DbgValue(RspPHIInBlk1, EmptyProps, DbgValue::Def)});
buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output,
MOutLocs, MInLocs, VLocs);
EXPECT_EQ(Output[0].size(), 0ul);
ASSERT_EQ(Output[1].size(), 1ul);
ASSERT_EQ(Output[2].size(), 1ul);
EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[1][0].second.ID, RspPHIInBlk1);
EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[2][0].second.ID, RspPHIInBlk1);
ClearOutputs();
VLocs[0].Vars.clear();
VLocs[1].Vars.clear();
MInLocs[1][0] = LiveInRsp;
MOutLocs[1][0] = LiveInRsp;
VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)});
VLocs[1].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)});
buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output,
MOutLocs, MInLocs, VLocs);
EXPECT_EQ(Output[0].size(), 0ul);
ASSERT_EQ(Output[1].size(), 1ul);
ASSERT_EQ(Output[2].size(), 1ul);
EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[1][0].second.ID, LiveInRsp);
EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[2][0].second.ID, LiveInRsp);
ClearOutputs();
VLocs[0].Vars.clear();
VLocs[1].Vars.clear();
}
TEST_F(InstrRefLDVTest, VLocNestedLoop) {
setupNestedLoops();
ASSERT_TRUE(MTracker->getNumLocs() == 1);
LocIdx RspLoc(0);
Register RAX = getRegByName("RAX");
LocIdx RaxLoc = MTracker->lookupOrTrackRegister(RAX);
unsigned EntryBlk = 0, Loop1Blk = 1, Loop2Blk = 2;
ValueIDNum LiveInRsp = ValueIDNum(EntryBlk, 0, RspLoc);
ValueIDNum LiveInRax = ValueIDNum(EntryBlk, 0, RaxLoc);
ValueIDNum RspPHIInBlk1 = ValueIDNum(Loop1Blk, 0, RspLoc);
ValueIDNum RspPHIInBlk2 = ValueIDNum(Loop2Blk, 0, RspLoc);
ValueIDNum RspDefInBlk2 = ValueIDNum(Loop2Blk, 1, RspLoc);
FuncValueTable MInLocs, MOutLocs;
std::tie(MInLocs, MOutLocs) = allocValueTables(5, 2);
initValueArray(MInLocs, 5, 2);
initValueArray(MOutLocs, 5, 2);
DebugVariable Var(FuncVariable, None, nullptr);
DbgValueProperties EmptyProps(EmptyExpr, false);
SmallSet<DebugVariable, 4> AllVars;
AllVars.insert(Var);
SmallPtrSet<MachineBasicBlock *, 5> AssignBlocks;
AssignBlocks.insert(MBB0);
AssignBlocks.insert(MBB1);
AssignBlocks.insert(MBB2);
AssignBlocks.insert(MBB3);
AssignBlocks.insert(MBB4);
SmallVector<VLocTracker, 5> VLocs;
VLocs.resize(5, VLocTracker(Overlaps, EmptyExpr));
InstrRefBasedLDV::LiveInsT Output;
for (unsigned int I = 0; I < 5; ++I) {
MInLocs[I][0] = MInLocs[I][1] = LiveInRsp;
MOutLocs[I][0] = MOutLocs[I][1] = LiveInRsp;
}
auto ClearOutputs = [&]() {
for (auto &Elem : Output)
Elem.clear();
};
Output.resize(5);
VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)});
buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output,
MOutLocs, MInLocs, VLocs);
EXPECT_EQ(Output[0].size(), 0ul);
ASSERT_EQ(Output[1].size(), 1ul);
ASSERT_EQ(Output[2].size(), 1ul);
ASSERT_EQ(Output[3].size(), 1ul);
ASSERT_EQ(Output[4].size(), 1ul);
EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[1][0].second.ID, LiveInRsp);
EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[2][0].second.ID, LiveInRsp);
EXPECT_EQ(Output[3][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[3][0].second.ID, LiveInRsp);
EXPECT_EQ(Output[4][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[4][0].second.ID, LiveInRsp);
ClearOutputs();
VLocs[0].Vars.clear();
VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)});
VLocs[2].Vars.insert({Var, DbgValue(LiveInRax, EmptyProps, DbgValue::Def)});
buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output,
MOutLocs, MInLocs, VLocs);
EXPECT_EQ(Output[0].size(), 0ul);
EXPECT_EQ(Output[1].size(), 0ul);
EXPECT_EQ(Output[2].size(), 0ul);
ASSERT_EQ(Output[3].size(), 1ul);
ASSERT_EQ(Output[4].size(), 1ul);
EXPECT_EQ(Output[3][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[3][0].second.ID, LiveInRax);
EXPECT_EQ(Output[4][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[4][0].second.ID, LiveInRax);
ClearOutputs();
VLocs[0].Vars.clear();
VLocs[2].Vars.clear();
VLocs[2].Vars.insert({Var, DbgValue(LiveInRax, EmptyProps, DbgValue::Def)});
buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output,
MOutLocs, MInLocs, VLocs);
EXPECT_EQ(Output[0].size(), 0ul);
EXPECT_EQ(Output[1].size(), 0ul);
EXPECT_EQ(Output[2].size(), 0ul);
ASSERT_EQ(Output[3].size(), 1ul);
ASSERT_EQ(Output[4].size(), 1ul);
EXPECT_EQ(Output[3][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[3][0].second.ID, LiveInRax);
EXPECT_EQ(Output[4][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[4][0].second.ID, LiveInRax);
ClearOutputs();
VLocs[2].Vars.clear();
VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)});
VLocs[3].Vars.insert({Var, DbgValue(LiveInRax, EmptyProps, DbgValue::Def)});
buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output,
MOutLocs, MInLocs, VLocs);
EXPECT_EQ(Output[0].size(), 0ul);
EXPECT_EQ(Output[1].size(), 0ul);
EXPECT_EQ(Output[2].size(), 0ul);
EXPECT_EQ(Output[3].size(), 0ul);
ASSERT_EQ(Output[4].size(), 1ul);
EXPECT_EQ(Output[4][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[4][0].second.ID, LiveInRax);
ClearOutputs();
VLocs[0].Vars.clear();
VLocs[3].Vars.clear();
VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)});
VLocs[1].Vars.insert({Var, DbgValue(LiveInRax, EmptyProps, DbgValue::Def)});
buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output,
MOutLocs, MInLocs, VLocs);
EXPECT_EQ(Output[0].size(), 0ul);
EXPECT_EQ(Output[1].size(), 0ul);
ASSERT_EQ(Output[2].size(), 1ul);
ASSERT_EQ(Output[3].size(), 1ul);
ASSERT_EQ(Output[4].size(), 1ul);
EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[2][0].second.ID, LiveInRax);
EXPECT_EQ(Output[3][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[3][0].second.ID, LiveInRax);
EXPECT_EQ(Output[4][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[4][0].second.ID, LiveInRax);
ClearOutputs();
VLocs[0].Vars.clear();
VLocs[1].Vars.clear();
VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)});
VLocs[2].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)});
buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output,
MOutLocs, MInLocs, VLocs);
EXPECT_EQ(Output[0].size(), 0ul);
EXPECT_EQ(Output[1].size(), 1ul);
EXPECT_EQ(Output[2].size(), 1ul);
ASSERT_EQ(Output[3].size(), 1ul);
ASSERT_EQ(Output[4].size(), 1ul);
EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[1][0].second.ID, LiveInRsp);
EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[2][0].second.ID, LiveInRsp);
EXPECT_EQ(Output[3][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[3][0].second.ID, LiveInRsp);
EXPECT_EQ(Output[4][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[4][0].second.ID, LiveInRsp);
ClearOutputs();
VLocs[0].Vars.clear();
VLocs[2].Vars.clear();
MInLocs[2][0] = RspPHIInBlk2;
MOutLocs[2][0] = LiveInRax;
VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)});
VLocs[2].Vars.insert({Var, DbgValue(LiveInRax, EmptyProps, DbgValue::Def)});
buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output,
MOutLocs, MInLocs, VLocs);
EXPECT_EQ(Output[0].size(), 0ul);
EXPECT_EQ(Output[1].size(), 0ul);
EXPECT_EQ(Output[2].size(), 0ul);
ASSERT_EQ(Output[3].size(), 1ul);
ASSERT_EQ(Output[4].size(), 1ul);
EXPECT_EQ(Output[3][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[3][0].second.ID, LiveInRax);
EXPECT_EQ(Output[4][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[4][0].second.ID, LiveInRax);
ClearOutputs();
VLocs[0].Vars.clear();
VLocs[2].Vars.clear();
MInLocs[1][0] = RspPHIInBlk1;
MOutLocs[1][0] = RspPHIInBlk1;
MInLocs[2][0] = RspPHIInBlk2;
MOutLocs[2][0] = RspDefInBlk2;
MInLocs[3][0] = RspDefInBlk2;
MOutLocs[3][0] = RspDefInBlk2;
VLocs[0].Vars.insert({Var, DbgValue(LiveInRsp, EmptyProps, DbgValue::Def)});
VLocs[2].Vars.insert({Var, DbgValue(RspDefInBlk2, EmptyProps, DbgValue::Def)});
buildVLocValueMap(OutermostLoc, AllVars, AssignBlocks, Output,
MOutLocs, MInLocs, VLocs);
EXPECT_EQ(Output[0].size(), 0ul);
ASSERT_EQ(Output[1].size(), 1ul);
ASSERT_EQ(Output[2].size(), 1ul);
ASSERT_EQ(Output[3].size(), 1ul);
ASSERT_EQ(Output[4].size(), 1ul);
EXPECT_EQ(Output[1][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[1][0].second.ID, RspPHIInBlk1);
EXPECT_EQ(Output[2][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[2][0].second.ID, RspPHIInBlk2);
EXPECT_EQ(Output[3][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[3][0].second.ID, RspDefInBlk2);
EXPECT_EQ(Output[4][0].second.Kind, DbgValue::Def);
EXPECT_EQ(Output[4][0].second.ID, RspDefInBlk2);
ClearOutputs();
VLocs[0].Vars.clear();
VLocs[2].Vars.clear();
}