14a5f522dSDiana Picus //===- MachineInstrTest.cpp -----------------------------------------------===// 24a5f522dSDiana Picus // 34a5f522dSDiana Picus // The LLVM Compiler Infrastructure 44a5f522dSDiana Picus // 54a5f522dSDiana Picus // This file is distributed under the University of Illinois Open Source 64a5f522dSDiana Picus // License. See LICENSE.TXT for details. 74a5f522dSDiana Picus // 84a5f522dSDiana Picus //===----------------------------------------------------------------------===// 94a5f522dSDiana Picus 104a5f522dSDiana Picus #include "llvm/CodeGen/MachineInstr.h" 114a5f522dSDiana Picus #include "llvm/CodeGen/MachineFunction.h" 124a5f522dSDiana Picus #include "llvm/CodeGen/MachineModuleInfo.h" 134a5f522dSDiana Picus #include "llvm/Support/TargetRegistry.h" 144a5f522dSDiana Picus #include "llvm/Support/TargetSelect.h" 154a5f522dSDiana Picus #include "llvm/Target/TargetFrameLowering.h" 164a5f522dSDiana Picus #include "llvm/Target/TargetInstrInfo.h" 174a5f522dSDiana Picus #include "llvm/Target/TargetLowering.h" 184a5f522dSDiana Picus #include "llvm/Target/TargetMachine.h" 194a5f522dSDiana Picus #include "llvm/Target/TargetOptions.h" 204a5f522dSDiana Picus #include "llvm/Target/TargetSubtargetInfo.h" 214a5f522dSDiana Picus #include "gtest/gtest.h" 224a5f522dSDiana Picus 234a5f522dSDiana Picus using namespace llvm; 244a5f522dSDiana Picus 254a5f522dSDiana Picus namespace { 264a5f522dSDiana Picus // Add a few Bogus backend classes so we can create MachineInstrs without 274a5f522dSDiana Picus // depending on a real target. 284a5f522dSDiana Picus class BogusTargetLowering : public TargetLowering { 294a5f522dSDiana Picus public: 304a5f522dSDiana Picus BogusTargetLowering(TargetMachine &TM) : TargetLowering(TM) {} 314a5f522dSDiana Picus }; 324a5f522dSDiana Picus 334a5f522dSDiana Picus class BogusFrameLowering : public TargetFrameLowering { 344a5f522dSDiana Picus public: 354a5f522dSDiana Picus BogusFrameLowering() 364a5f522dSDiana Picus : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, 4, 4) {} 374a5f522dSDiana Picus 384a5f522dSDiana Picus void emitPrologue(MachineFunction &MF, 394a5f522dSDiana Picus MachineBasicBlock &MBB) const override {} 404a5f522dSDiana Picus void emitEpilogue(MachineFunction &MF, 414a5f522dSDiana Picus MachineBasicBlock &MBB) const override {} 424a5f522dSDiana Picus bool hasFP(const MachineFunction &MF) const override { return false; } 434a5f522dSDiana Picus }; 444a5f522dSDiana Picus 454a5f522dSDiana Picus class BogusSubtarget : public TargetSubtargetInfo { 464a5f522dSDiana Picus public: 474a5f522dSDiana Picus BogusSubtarget(TargetMachine &TM) 484a5f522dSDiana Picus : TargetSubtargetInfo(Triple(""), "", "", {}, {}, nullptr, nullptr, 494a5f522dSDiana Picus nullptr, nullptr, nullptr, nullptr, nullptr), 504a5f522dSDiana Picus FL(), TL(TM) {} 514a5f522dSDiana Picus ~BogusSubtarget() override {} 524a5f522dSDiana Picus 534a5f522dSDiana Picus const TargetFrameLowering *getFrameLowering() const override { return &FL; } 544a5f522dSDiana Picus 554a5f522dSDiana Picus const TargetLowering *getTargetLowering() const override { return &TL; } 564a5f522dSDiana Picus 574a5f522dSDiana Picus const TargetInstrInfo *getInstrInfo() const override { return &TII; } 584a5f522dSDiana Picus 594a5f522dSDiana Picus private: 604a5f522dSDiana Picus BogusFrameLowering FL; 614a5f522dSDiana Picus BogusTargetLowering TL; 624a5f522dSDiana Picus TargetInstrInfo TII; 634a5f522dSDiana Picus }; 644a5f522dSDiana Picus 65*bb8507e6SMatthias Braun class BogusTargetMachine : public LLVMTargetMachine { 664a5f522dSDiana Picus public: 674a5f522dSDiana Picus BogusTargetMachine() 68*bb8507e6SMatthias Braun : LLVMTargetMachine(Target(), "", Triple(""), "", "", TargetOptions(), 694a5f522dSDiana Picus Reloc::Static, CodeModel::Small, CodeGenOpt::Default), 704a5f522dSDiana Picus ST(*this) {} 714a5f522dSDiana Picus ~BogusTargetMachine() override {} 724a5f522dSDiana Picus 734a5f522dSDiana Picus const TargetSubtargetInfo *getSubtargetImpl(const Function &) const override { 744a5f522dSDiana Picus return &ST; 754a5f522dSDiana Picus } 764a5f522dSDiana Picus 774a5f522dSDiana Picus private: 784a5f522dSDiana Picus BogusSubtarget ST; 794a5f522dSDiana Picus }; 804a5f522dSDiana Picus 814a5f522dSDiana Picus std::unique_ptr<BogusTargetMachine> createTargetMachine() { 824a5f522dSDiana Picus return llvm::make_unique<BogusTargetMachine>(); 834a5f522dSDiana Picus } 844a5f522dSDiana Picus 854a5f522dSDiana Picus std::unique_ptr<MachineFunction> createMachineFunction() { 864a5f522dSDiana Picus LLVMContext Ctx; 874a5f522dSDiana Picus Module M("Module", Ctx); 884a5f522dSDiana Picus auto Type = FunctionType::get(Type::getVoidTy(Ctx), false); 894a5f522dSDiana Picus auto F = Function::Create(Type, GlobalValue::ExternalLinkage, "Test", &M); 904a5f522dSDiana Picus 914a5f522dSDiana Picus auto TM = createTargetMachine(); 924a5f522dSDiana Picus unsigned FunctionNum = 42; 934a5f522dSDiana Picus MachineModuleInfo MMI(TM.get()); 944a5f522dSDiana Picus 954a5f522dSDiana Picus return llvm::make_unique<MachineFunction>(F, *TM, FunctionNum, MMI); 964a5f522dSDiana Picus } 974a5f522dSDiana Picus 984a5f522dSDiana Picus // This test makes sure that MachineInstr::isIdenticalTo handles Defs correctly 994a5f522dSDiana Picus // for various combinations of IgnoreDefs, and also that it is symmetrical. 1004a5f522dSDiana Picus TEST(IsIdenticalToTest, DifferentDefs) { 1014a5f522dSDiana Picus auto MF = createMachineFunction(); 1024a5f522dSDiana Picus 1034a5f522dSDiana Picus unsigned short NumOps = 2; 1044a5f522dSDiana Picus unsigned char NumDefs = 1; 1054a5f522dSDiana Picus MCOperandInfo OpInfo[] = { 1064a5f522dSDiana Picus {0, 0, MCOI::OPERAND_REGISTER, 0}, 1074a5f522dSDiana Picus {0, 1 << MCOI::OptionalDef, MCOI::OPERAND_REGISTER, 0}}; 1084a5f522dSDiana Picus MCInstrDesc MCID = { 1094a5f522dSDiana Picus 0, NumOps, NumDefs, 0, 0, 1ULL << MCID::HasOptionalDef, 1104a5f522dSDiana Picus 0, nullptr, nullptr, OpInfo, 0, nullptr}; 1114a5f522dSDiana Picus 1124a5f522dSDiana Picus // Create two MIs with different virtual reg defs and the same uses. 1134a5f522dSDiana Picus unsigned VirtualDef1 = -42; // The value doesn't matter, but the sign does. 1144a5f522dSDiana Picus unsigned VirtualDef2 = -43; 1154a5f522dSDiana Picus unsigned VirtualUse = -44; 1164a5f522dSDiana Picus 1174a5f522dSDiana Picus auto MI1 = MF->CreateMachineInstr(MCID, DebugLoc()); 1184a5f522dSDiana Picus MI1->addOperand(*MF, MachineOperand::CreateReg(VirtualDef1, /*isDef*/ true)); 1194a5f522dSDiana Picus MI1->addOperand(*MF, MachineOperand::CreateReg(VirtualUse, /*isDef*/ false)); 1204a5f522dSDiana Picus 1214a5f522dSDiana Picus auto MI2 = MF->CreateMachineInstr(MCID, DebugLoc()); 1224a5f522dSDiana Picus MI2->addOperand(*MF, MachineOperand::CreateReg(VirtualDef2, /*isDef*/ true)); 1234a5f522dSDiana Picus MI2->addOperand(*MF, MachineOperand::CreateReg(VirtualUse, /*isDef*/ false)); 1244a5f522dSDiana Picus 1254a5f522dSDiana Picus // Check that they are identical when we ignore virtual register defs, but not 1264a5f522dSDiana Picus // when we check defs. 1274a5f522dSDiana Picus ASSERT_FALSE(MI1->isIdenticalTo(*MI2, MachineInstr::CheckDefs)); 1284a5f522dSDiana Picus ASSERT_FALSE(MI2->isIdenticalTo(*MI1, MachineInstr::CheckDefs)); 1294a5f522dSDiana Picus 1304a5f522dSDiana Picus ASSERT_TRUE(MI1->isIdenticalTo(*MI2, MachineInstr::IgnoreVRegDefs)); 1314a5f522dSDiana Picus ASSERT_TRUE(MI2->isIdenticalTo(*MI1, MachineInstr::IgnoreVRegDefs)); 1324a5f522dSDiana Picus 1334a5f522dSDiana Picus // Create two MIs with different virtual reg defs, and a def or use of a 1344a5f522dSDiana Picus // sentinel register. 1354a5f522dSDiana Picus unsigned SentinelReg = 0; 1364a5f522dSDiana Picus 1374a5f522dSDiana Picus auto MI3 = MF->CreateMachineInstr(MCID, DebugLoc()); 1384a5f522dSDiana Picus MI3->addOperand(*MF, MachineOperand::CreateReg(VirtualDef1, /*isDef*/ true)); 1394a5f522dSDiana Picus MI3->addOperand(*MF, MachineOperand::CreateReg(SentinelReg, /*isDef*/ true)); 1404a5f522dSDiana Picus 1414a5f522dSDiana Picus auto MI4 = MF->CreateMachineInstr(MCID, DebugLoc()); 1424a5f522dSDiana Picus MI4->addOperand(*MF, MachineOperand::CreateReg(VirtualDef2, /*isDef*/ true)); 1434a5f522dSDiana Picus MI4->addOperand(*MF, MachineOperand::CreateReg(SentinelReg, /*isDef*/ false)); 1444a5f522dSDiana Picus 1454a5f522dSDiana Picus // Check that they are never identical. 1464a5f522dSDiana Picus ASSERT_FALSE(MI3->isIdenticalTo(*MI4, MachineInstr::CheckDefs)); 1474a5f522dSDiana Picus ASSERT_FALSE(MI4->isIdenticalTo(*MI3, MachineInstr::CheckDefs)); 1484a5f522dSDiana Picus 1494a5f522dSDiana Picus ASSERT_FALSE(MI3->isIdenticalTo(*MI4, MachineInstr::IgnoreVRegDefs)); 1504a5f522dSDiana Picus ASSERT_FALSE(MI4->isIdenticalTo(*MI3, MachineInstr::IgnoreVRegDefs)); 1514a5f522dSDiana Picus } 1524a5f522dSDiana Picus 1534a5f522dSDiana Picus // Check that MachineInstrExpressionTrait::isEqual is symmetric and in sync with 1544a5f522dSDiana Picus // MachineInstrExpressionTrait::getHashValue 1554a5f522dSDiana Picus void checkHashAndIsEqualMatch(MachineInstr *MI1, MachineInstr *MI2) { 1564a5f522dSDiana Picus bool IsEqual1 = MachineInstrExpressionTrait::isEqual(MI1, MI2); 1574a5f522dSDiana Picus bool IsEqual2 = MachineInstrExpressionTrait::isEqual(MI2, MI1); 1584a5f522dSDiana Picus 1594a5f522dSDiana Picus ASSERT_EQ(IsEqual1, IsEqual2); 1604a5f522dSDiana Picus 1614a5f522dSDiana Picus auto Hash1 = MachineInstrExpressionTrait::getHashValue(MI1); 1624a5f522dSDiana Picus auto Hash2 = MachineInstrExpressionTrait::getHashValue(MI2); 1634a5f522dSDiana Picus 1644a5f522dSDiana Picus ASSERT_EQ(IsEqual1, Hash1 == Hash2); 1654a5f522dSDiana Picus } 1664a5f522dSDiana Picus 1674a5f522dSDiana Picus // This test makes sure that MachineInstrExpressionTraits::isEqual is in sync 1684a5f522dSDiana Picus // with MachineInstrExpressionTraits::getHashValue. 1694a5f522dSDiana Picus TEST(MachineInstrExpressionTraitTest, IsEqualAgreesWithGetHashValue) { 1704a5f522dSDiana Picus auto MF = createMachineFunction(); 1714a5f522dSDiana Picus 1724a5f522dSDiana Picus unsigned short NumOps = 2; 1734a5f522dSDiana Picus unsigned char NumDefs = 1; 1744a5f522dSDiana Picus MCOperandInfo OpInfo[] = { 1754a5f522dSDiana Picus {0, 0, MCOI::OPERAND_REGISTER, 0}, 1764a5f522dSDiana Picus {0, 1 << MCOI::OptionalDef, MCOI::OPERAND_REGISTER, 0}}; 1774a5f522dSDiana Picus MCInstrDesc MCID = { 1784a5f522dSDiana Picus 0, NumOps, NumDefs, 0, 0, 1ULL << MCID::HasOptionalDef, 1794a5f522dSDiana Picus 0, nullptr, nullptr, OpInfo, 0, nullptr}; 1804a5f522dSDiana Picus 1814a5f522dSDiana Picus // Define a series of instructions with different kinds of operands and make 1824a5f522dSDiana Picus // sure that the hash function is consistent with isEqual for various 1834a5f522dSDiana Picus // combinations of them. 1844a5f522dSDiana Picus unsigned VirtualDef1 = -42; 1854a5f522dSDiana Picus unsigned VirtualDef2 = -43; 1864a5f522dSDiana Picus unsigned VirtualReg = -44; 1874a5f522dSDiana Picus unsigned SentinelReg = 0; 1884a5f522dSDiana Picus unsigned PhysicalReg = 45; 1894a5f522dSDiana Picus 1904a5f522dSDiana Picus auto VD1VU = MF->CreateMachineInstr(MCID, DebugLoc()); 1914a5f522dSDiana Picus VD1VU->addOperand(*MF, 1924a5f522dSDiana Picus MachineOperand::CreateReg(VirtualDef1, /*isDef*/ true)); 1934a5f522dSDiana Picus VD1VU->addOperand(*MF, 1944a5f522dSDiana Picus MachineOperand::CreateReg(VirtualReg, /*isDef*/ false)); 1954a5f522dSDiana Picus 1964a5f522dSDiana Picus auto VD2VU = MF->CreateMachineInstr(MCID, DebugLoc()); 1974a5f522dSDiana Picus VD2VU->addOperand(*MF, 1984a5f522dSDiana Picus MachineOperand::CreateReg(VirtualDef2, /*isDef*/ true)); 1994a5f522dSDiana Picus VD2VU->addOperand(*MF, 2004a5f522dSDiana Picus MachineOperand::CreateReg(VirtualReg, /*isDef*/ false)); 2014a5f522dSDiana Picus 2024a5f522dSDiana Picus auto VD1SU = MF->CreateMachineInstr(MCID, DebugLoc()); 2034a5f522dSDiana Picus VD1SU->addOperand(*MF, 2044a5f522dSDiana Picus MachineOperand::CreateReg(VirtualDef1, /*isDef*/ true)); 2054a5f522dSDiana Picus VD1SU->addOperand(*MF, 2064a5f522dSDiana Picus MachineOperand::CreateReg(SentinelReg, /*isDef*/ false)); 2074a5f522dSDiana Picus 2084a5f522dSDiana Picus auto VD1SD = MF->CreateMachineInstr(MCID, DebugLoc()); 2094a5f522dSDiana Picus VD1SD->addOperand(*MF, 2104a5f522dSDiana Picus MachineOperand::CreateReg(VirtualDef1, /*isDef*/ true)); 2114a5f522dSDiana Picus VD1SD->addOperand(*MF, 2124a5f522dSDiana Picus MachineOperand::CreateReg(SentinelReg, /*isDef*/ true)); 2134a5f522dSDiana Picus 2144a5f522dSDiana Picus auto VD2PU = MF->CreateMachineInstr(MCID, DebugLoc()); 2154a5f522dSDiana Picus VD2PU->addOperand(*MF, 2164a5f522dSDiana Picus MachineOperand::CreateReg(VirtualDef2, /*isDef*/ true)); 2174a5f522dSDiana Picus VD2PU->addOperand(*MF, 2184a5f522dSDiana Picus MachineOperand::CreateReg(PhysicalReg, /*isDef*/ false)); 2194a5f522dSDiana Picus 2204a5f522dSDiana Picus auto VD2PD = MF->CreateMachineInstr(MCID, DebugLoc()); 2214a5f522dSDiana Picus VD2PD->addOperand(*MF, 2224a5f522dSDiana Picus MachineOperand::CreateReg(VirtualDef2, /*isDef*/ true)); 2234a5f522dSDiana Picus VD2PD->addOperand(*MF, 2244a5f522dSDiana Picus MachineOperand::CreateReg(PhysicalReg, /*isDef*/ true)); 2254a5f522dSDiana Picus 2264a5f522dSDiana Picus checkHashAndIsEqualMatch(VD1VU, VD2VU); 2274a5f522dSDiana Picus checkHashAndIsEqualMatch(VD1VU, VD1SU); 2284a5f522dSDiana Picus checkHashAndIsEqualMatch(VD1VU, VD1SD); 2294a5f522dSDiana Picus checkHashAndIsEqualMatch(VD1VU, VD2PU); 2304a5f522dSDiana Picus checkHashAndIsEqualMatch(VD1VU, VD2PD); 2314a5f522dSDiana Picus 2324a5f522dSDiana Picus checkHashAndIsEqualMatch(VD2VU, VD1SU); 2334a5f522dSDiana Picus checkHashAndIsEqualMatch(VD2VU, VD1SD); 2344a5f522dSDiana Picus checkHashAndIsEqualMatch(VD2VU, VD2PU); 2354a5f522dSDiana Picus checkHashAndIsEqualMatch(VD2VU, VD2PD); 2364a5f522dSDiana Picus 2374a5f522dSDiana Picus checkHashAndIsEqualMatch(VD1SU, VD1SD); 2384a5f522dSDiana Picus checkHashAndIsEqualMatch(VD1SU, VD2PU); 2394a5f522dSDiana Picus checkHashAndIsEqualMatch(VD1SU, VD2PD); 2404a5f522dSDiana Picus 2414a5f522dSDiana Picus checkHashAndIsEqualMatch(VD1SD, VD2PU); 2424a5f522dSDiana Picus checkHashAndIsEqualMatch(VD1SD, VD2PD); 2434a5f522dSDiana Picus 2444a5f522dSDiana Picus checkHashAndIsEqualMatch(VD2PU, VD2PD); 2454a5f522dSDiana Picus } 2464a5f522dSDiana Picus } // end namespace 247