1 //===- MachineInstrTest.cpp -----------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "llvm/CodeGen/MachineInstr.h" 11 #include "llvm/CodeGen/MachineFunction.h" 12 #include "llvm/CodeGen/MachineModuleInfo.h" 13 #include "llvm/CodeGen/TargetFrameLowering.h" 14 #include "llvm/CodeGen/TargetInstrInfo.h" 15 #include "llvm/CodeGen/TargetLowering.h" 16 #include "llvm/CodeGen/TargetSubtargetInfo.h" 17 #include "llvm/Support/TargetRegistry.h" 18 #include "llvm/Support/TargetSelect.h" 19 #include "llvm/Target/TargetMachine.h" 20 #include "llvm/Target/TargetOptions.h" 21 #include "gtest/gtest.h" 22 23 using namespace llvm; 24 25 namespace { 26 // Add a few Bogus backend classes so we can create MachineInstrs without 27 // depending on a real target. 28 class BogusTargetLowering : public TargetLowering { 29 public: 30 BogusTargetLowering(TargetMachine &TM) : TargetLowering(TM) {} 31 }; 32 33 class BogusFrameLowering : public TargetFrameLowering { 34 public: 35 BogusFrameLowering() 36 : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, 4, 4) {} 37 38 void emitPrologue(MachineFunction &MF, 39 MachineBasicBlock &MBB) const override {} 40 void emitEpilogue(MachineFunction &MF, 41 MachineBasicBlock &MBB) const override {} 42 bool hasFP(const MachineFunction &MF) const override { return false; } 43 }; 44 45 class BogusSubtarget : public TargetSubtargetInfo { 46 public: 47 BogusSubtarget(TargetMachine &TM) 48 : TargetSubtargetInfo(Triple(""), "", "", {}, {}, nullptr, nullptr, 49 nullptr, nullptr, nullptr, nullptr, nullptr), 50 FL(), TL(TM) {} 51 ~BogusSubtarget() override {} 52 53 const TargetFrameLowering *getFrameLowering() const override { return &FL; } 54 55 const TargetLowering *getTargetLowering() const override { return &TL; } 56 57 const TargetInstrInfo *getInstrInfo() const override { return &TII; } 58 59 private: 60 BogusFrameLowering FL; 61 BogusTargetLowering TL; 62 TargetInstrInfo TII; 63 }; 64 65 class BogusTargetMachine : public LLVMTargetMachine { 66 public: 67 BogusTargetMachine() 68 : LLVMTargetMachine(Target(), "", Triple(""), "", "", TargetOptions(), 69 Reloc::Static, CodeModel::Small, CodeGenOpt::Default), 70 ST(*this) {} 71 ~BogusTargetMachine() override {} 72 73 const TargetSubtargetInfo *getSubtargetImpl(const Function &) const override { 74 return &ST; 75 } 76 77 private: 78 BogusSubtarget ST; 79 }; 80 81 std::unique_ptr<BogusTargetMachine> createTargetMachine() { 82 return llvm::make_unique<BogusTargetMachine>(); 83 } 84 85 std::unique_ptr<MachineFunction> createMachineFunction() { 86 LLVMContext Ctx; 87 Module M("Module", Ctx); 88 auto Type = FunctionType::get(Type::getVoidTy(Ctx), false); 89 auto F = Function::Create(Type, GlobalValue::ExternalLinkage, "Test", &M); 90 91 auto TM = createTargetMachine(); 92 unsigned FunctionNum = 42; 93 MachineModuleInfo MMI(TM.get()); 94 const TargetSubtargetInfo &STI = *TM->getSubtargetImpl(*F); 95 96 return llvm::make_unique<MachineFunction>(*F, *TM, STI, FunctionNum, MMI); 97 } 98 99 // This test makes sure that MachineInstr::isIdenticalTo handles Defs correctly 100 // for various combinations of IgnoreDefs, and also that it is symmetrical. 101 TEST(IsIdenticalToTest, DifferentDefs) { 102 auto MF = createMachineFunction(); 103 104 unsigned short NumOps = 2; 105 unsigned char NumDefs = 1; 106 MCOperandInfo OpInfo[] = { 107 {0, 0, MCOI::OPERAND_REGISTER, 0}, 108 {0, 1 << MCOI::OptionalDef, MCOI::OPERAND_REGISTER, 0}}; 109 MCInstrDesc MCID = { 110 0, NumOps, NumDefs, 0, 0, 1ULL << MCID::HasOptionalDef, 111 0, nullptr, nullptr, OpInfo, 0, nullptr}; 112 113 // Create two MIs with different virtual reg defs and the same uses. 114 unsigned VirtualDef1 = -42; // The value doesn't matter, but the sign does. 115 unsigned VirtualDef2 = -43; 116 unsigned VirtualUse = -44; 117 118 auto MI1 = MF->CreateMachineInstr(MCID, DebugLoc()); 119 MI1->addOperand(*MF, MachineOperand::CreateReg(VirtualDef1, /*isDef*/ true)); 120 MI1->addOperand(*MF, MachineOperand::CreateReg(VirtualUse, /*isDef*/ false)); 121 122 auto MI2 = MF->CreateMachineInstr(MCID, DebugLoc()); 123 MI2->addOperand(*MF, MachineOperand::CreateReg(VirtualDef2, /*isDef*/ true)); 124 MI2->addOperand(*MF, MachineOperand::CreateReg(VirtualUse, /*isDef*/ false)); 125 126 // Check that they are identical when we ignore virtual register defs, but not 127 // when we check defs. 128 ASSERT_FALSE(MI1->isIdenticalTo(*MI2, MachineInstr::CheckDefs)); 129 ASSERT_FALSE(MI2->isIdenticalTo(*MI1, MachineInstr::CheckDefs)); 130 131 ASSERT_TRUE(MI1->isIdenticalTo(*MI2, MachineInstr::IgnoreVRegDefs)); 132 ASSERT_TRUE(MI2->isIdenticalTo(*MI1, MachineInstr::IgnoreVRegDefs)); 133 134 // Create two MIs with different virtual reg defs, and a def or use of a 135 // sentinel register. 136 unsigned SentinelReg = 0; 137 138 auto MI3 = MF->CreateMachineInstr(MCID, DebugLoc()); 139 MI3->addOperand(*MF, MachineOperand::CreateReg(VirtualDef1, /*isDef*/ true)); 140 MI3->addOperand(*MF, MachineOperand::CreateReg(SentinelReg, /*isDef*/ true)); 141 142 auto MI4 = MF->CreateMachineInstr(MCID, DebugLoc()); 143 MI4->addOperand(*MF, MachineOperand::CreateReg(VirtualDef2, /*isDef*/ true)); 144 MI4->addOperand(*MF, MachineOperand::CreateReg(SentinelReg, /*isDef*/ false)); 145 146 // Check that they are never identical. 147 ASSERT_FALSE(MI3->isIdenticalTo(*MI4, MachineInstr::CheckDefs)); 148 ASSERT_FALSE(MI4->isIdenticalTo(*MI3, MachineInstr::CheckDefs)); 149 150 ASSERT_FALSE(MI3->isIdenticalTo(*MI4, MachineInstr::IgnoreVRegDefs)); 151 ASSERT_FALSE(MI4->isIdenticalTo(*MI3, MachineInstr::IgnoreVRegDefs)); 152 } 153 154 // Check that MachineInstrExpressionTrait::isEqual is symmetric and in sync with 155 // MachineInstrExpressionTrait::getHashValue 156 void checkHashAndIsEqualMatch(MachineInstr *MI1, MachineInstr *MI2) { 157 bool IsEqual1 = MachineInstrExpressionTrait::isEqual(MI1, MI2); 158 bool IsEqual2 = MachineInstrExpressionTrait::isEqual(MI2, MI1); 159 160 ASSERT_EQ(IsEqual1, IsEqual2); 161 162 auto Hash1 = MachineInstrExpressionTrait::getHashValue(MI1); 163 auto Hash2 = MachineInstrExpressionTrait::getHashValue(MI2); 164 165 ASSERT_EQ(IsEqual1, Hash1 == Hash2); 166 } 167 168 // This test makes sure that MachineInstrExpressionTraits::isEqual is in sync 169 // with MachineInstrExpressionTraits::getHashValue. 170 TEST(MachineInstrExpressionTraitTest, IsEqualAgreesWithGetHashValue) { 171 auto MF = createMachineFunction(); 172 173 unsigned short NumOps = 2; 174 unsigned char NumDefs = 1; 175 MCOperandInfo OpInfo[] = { 176 {0, 0, MCOI::OPERAND_REGISTER, 0}, 177 {0, 1 << MCOI::OptionalDef, MCOI::OPERAND_REGISTER, 0}}; 178 MCInstrDesc MCID = { 179 0, NumOps, NumDefs, 0, 0, 1ULL << MCID::HasOptionalDef, 180 0, nullptr, nullptr, OpInfo, 0, nullptr}; 181 182 // Define a series of instructions with different kinds of operands and make 183 // sure that the hash function is consistent with isEqual for various 184 // combinations of them. 185 unsigned VirtualDef1 = -42; 186 unsigned VirtualDef2 = -43; 187 unsigned VirtualReg = -44; 188 unsigned SentinelReg = 0; 189 unsigned PhysicalReg = 45; 190 191 auto VD1VU = MF->CreateMachineInstr(MCID, DebugLoc()); 192 VD1VU->addOperand(*MF, 193 MachineOperand::CreateReg(VirtualDef1, /*isDef*/ true)); 194 VD1VU->addOperand(*MF, 195 MachineOperand::CreateReg(VirtualReg, /*isDef*/ false)); 196 197 auto VD2VU = MF->CreateMachineInstr(MCID, DebugLoc()); 198 VD2VU->addOperand(*MF, 199 MachineOperand::CreateReg(VirtualDef2, /*isDef*/ true)); 200 VD2VU->addOperand(*MF, 201 MachineOperand::CreateReg(VirtualReg, /*isDef*/ false)); 202 203 auto VD1SU = MF->CreateMachineInstr(MCID, DebugLoc()); 204 VD1SU->addOperand(*MF, 205 MachineOperand::CreateReg(VirtualDef1, /*isDef*/ true)); 206 VD1SU->addOperand(*MF, 207 MachineOperand::CreateReg(SentinelReg, /*isDef*/ false)); 208 209 auto VD1SD = MF->CreateMachineInstr(MCID, DebugLoc()); 210 VD1SD->addOperand(*MF, 211 MachineOperand::CreateReg(VirtualDef1, /*isDef*/ true)); 212 VD1SD->addOperand(*MF, 213 MachineOperand::CreateReg(SentinelReg, /*isDef*/ true)); 214 215 auto VD2PU = MF->CreateMachineInstr(MCID, DebugLoc()); 216 VD2PU->addOperand(*MF, 217 MachineOperand::CreateReg(VirtualDef2, /*isDef*/ true)); 218 VD2PU->addOperand(*MF, 219 MachineOperand::CreateReg(PhysicalReg, /*isDef*/ false)); 220 221 auto VD2PD = MF->CreateMachineInstr(MCID, DebugLoc()); 222 VD2PD->addOperand(*MF, 223 MachineOperand::CreateReg(VirtualDef2, /*isDef*/ true)); 224 VD2PD->addOperand(*MF, 225 MachineOperand::CreateReg(PhysicalReg, /*isDef*/ true)); 226 227 checkHashAndIsEqualMatch(VD1VU, VD2VU); 228 checkHashAndIsEqualMatch(VD1VU, VD1SU); 229 checkHashAndIsEqualMatch(VD1VU, VD1SD); 230 checkHashAndIsEqualMatch(VD1VU, VD2PU); 231 checkHashAndIsEqualMatch(VD1VU, VD2PD); 232 233 checkHashAndIsEqualMatch(VD2VU, VD1SU); 234 checkHashAndIsEqualMatch(VD2VU, VD1SD); 235 checkHashAndIsEqualMatch(VD2VU, VD2PU); 236 checkHashAndIsEqualMatch(VD2VU, VD2PD); 237 238 checkHashAndIsEqualMatch(VD1SU, VD1SD); 239 checkHashAndIsEqualMatch(VD1SU, VD2PU); 240 checkHashAndIsEqualMatch(VD1SU, VD2PD); 241 242 checkHashAndIsEqualMatch(VD1SD, VD2PU); 243 checkHashAndIsEqualMatch(VD1SD, VD2PD); 244 245 checkHashAndIsEqualMatch(VD2PU, VD2PD); 246 } 247 } // end namespace 248