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/Support/TargetRegistry.h" 14 #include "llvm/Support/TargetSelect.h" 15 #include "llvm/CodeGen/TargetFrameLowering.h" 16 #include "llvm/Target/TargetInstrInfo.h" 17 #include "llvm/Target/TargetLowering.h" 18 #include "llvm/Target/TargetMachine.h" 19 #include "llvm/Target/TargetOptions.h" 20 #include "llvm/Target/TargetSubtargetInfo.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 95 return llvm::make_unique<MachineFunction>(F, *TM, FunctionNum, MMI); 96 } 97 98 // This test makes sure that MachineInstr::isIdenticalTo handles Defs correctly 99 // for various combinations of IgnoreDefs, and also that it is symmetrical. 100 TEST(IsIdenticalToTest, DifferentDefs) { 101 auto MF = createMachineFunction(); 102 103 unsigned short NumOps = 2; 104 unsigned char NumDefs = 1; 105 MCOperandInfo OpInfo[] = { 106 {0, 0, MCOI::OPERAND_REGISTER, 0}, 107 {0, 1 << MCOI::OptionalDef, MCOI::OPERAND_REGISTER, 0}}; 108 MCInstrDesc MCID = { 109 0, NumOps, NumDefs, 0, 0, 1ULL << MCID::HasOptionalDef, 110 0, nullptr, nullptr, OpInfo, 0, nullptr}; 111 112 // Create two MIs with different virtual reg defs and the same uses. 113 unsigned VirtualDef1 = -42; // The value doesn't matter, but the sign does. 114 unsigned VirtualDef2 = -43; 115 unsigned VirtualUse = -44; 116 117 auto MI1 = MF->CreateMachineInstr(MCID, DebugLoc()); 118 MI1->addOperand(*MF, MachineOperand::CreateReg(VirtualDef1, /*isDef*/ true)); 119 MI1->addOperand(*MF, MachineOperand::CreateReg(VirtualUse, /*isDef*/ false)); 120 121 auto MI2 = MF->CreateMachineInstr(MCID, DebugLoc()); 122 MI2->addOperand(*MF, MachineOperand::CreateReg(VirtualDef2, /*isDef*/ true)); 123 MI2->addOperand(*MF, MachineOperand::CreateReg(VirtualUse, /*isDef*/ false)); 124 125 // Check that they are identical when we ignore virtual register defs, but not 126 // when we check defs. 127 ASSERT_FALSE(MI1->isIdenticalTo(*MI2, MachineInstr::CheckDefs)); 128 ASSERT_FALSE(MI2->isIdenticalTo(*MI1, MachineInstr::CheckDefs)); 129 130 ASSERT_TRUE(MI1->isIdenticalTo(*MI2, MachineInstr::IgnoreVRegDefs)); 131 ASSERT_TRUE(MI2->isIdenticalTo(*MI1, MachineInstr::IgnoreVRegDefs)); 132 133 // Create two MIs with different virtual reg defs, and a def or use of a 134 // sentinel register. 135 unsigned SentinelReg = 0; 136 137 auto MI3 = MF->CreateMachineInstr(MCID, DebugLoc()); 138 MI3->addOperand(*MF, MachineOperand::CreateReg(VirtualDef1, /*isDef*/ true)); 139 MI3->addOperand(*MF, MachineOperand::CreateReg(SentinelReg, /*isDef*/ true)); 140 141 auto MI4 = MF->CreateMachineInstr(MCID, DebugLoc()); 142 MI4->addOperand(*MF, MachineOperand::CreateReg(VirtualDef2, /*isDef*/ true)); 143 MI4->addOperand(*MF, MachineOperand::CreateReg(SentinelReg, /*isDef*/ false)); 144 145 // Check that they are never identical. 146 ASSERT_FALSE(MI3->isIdenticalTo(*MI4, MachineInstr::CheckDefs)); 147 ASSERT_FALSE(MI4->isIdenticalTo(*MI3, MachineInstr::CheckDefs)); 148 149 ASSERT_FALSE(MI3->isIdenticalTo(*MI4, MachineInstr::IgnoreVRegDefs)); 150 ASSERT_FALSE(MI4->isIdenticalTo(*MI3, MachineInstr::IgnoreVRegDefs)); 151 } 152 153 // Check that MachineInstrExpressionTrait::isEqual is symmetric and in sync with 154 // MachineInstrExpressionTrait::getHashValue 155 void checkHashAndIsEqualMatch(MachineInstr *MI1, MachineInstr *MI2) { 156 bool IsEqual1 = MachineInstrExpressionTrait::isEqual(MI1, MI2); 157 bool IsEqual2 = MachineInstrExpressionTrait::isEqual(MI2, MI1); 158 159 ASSERT_EQ(IsEqual1, IsEqual2); 160 161 auto Hash1 = MachineInstrExpressionTrait::getHashValue(MI1); 162 auto Hash2 = MachineInstrExpressionTrait::getHashValue(MI2); 163 164 ASSERT_EQ(IsEqual1, Hash1 == Hash2); 165 } 166 167 // This test makes sure that MachineInstrExpressionTraits::isEqual is in sync 168 // with MachineInstrExpressionTraits::getHashValue. 169 TEST(MachineInstrExpressionTraitTest, IsEqualAgreesWithGetHashValue) { 170 auto MF = createMachineFunction(); 171 172 unsigned short NumOps = 2; 173 unsigned char NumDefs = 1; 174 MCOperandInfo OpInfo[] = { 175 {0, 0, MCOI::OPERAND_REGISTER, 0}, 176 {0, 1 << MCOI::OptionalDef, MCOI::OPERAND_REGISTER, 0}}; 177 MCInstrDesc MCID = { 178 0, NumOps, NumDefs, 0, 0, 1ULL << MCID::HasOptionalDef, 179 0, nullptr, nullptr, OpInfo, 0, nullptr}; 180 181 // Define a series of instructions with different kinds of operands and make 182 // sure that the hash function is consistent with isEqual for various 183 // combinations of them. 184 unsigned VirtualDef1 = -42; 185 unsigned VirtualDef2 = -43; 186 unsigned VirtualReg = -44; 187 unsigned SentinelReg = 0; 188 unsigned PhysicalReg = 45; 189 190 auto VD1VU = MF->CreateMachineInstr(MCID, DebugLoc()); 191 VD1VU->addOperand(*MF, 192 MachineOperand::CreateReg(VirtualDef1, /*isDef*/ true)); 193 VD1VU->addOperand(*MF, 194 MachineOperand::CreateReg(VirtualReg, /*isDef*/ false)); 195 196 auto VD2VU = MF->CreateMachineInstr(MCID, DebugLoc()); 197 VD2VU->addOperand(*MF, 198 MachineOperand::CreateReg(VirtualDef2, /*isDef*/ true)); 199 VD2VU->addOperand(*MF, 200 MachineOperand::CreateReg(VirtualReg, /*isDef*/ false)); 201 202 auto VD1SU = MF->CreateMachineInstr(MCID, DebugLoc()); 203 VD1SU->addOperand(*MF, 204 MachineOperand::CreateReg(VirtualDef1, /*isDef*/ true)); 205 VD1SU->addOperand(*MF, 206 MachineOperand::CreateReg(SentinelReg, /*isDef*/ false)); 207 208 auto VD1SD = MF->CreateMachineInstr(MCID, DebugLoc()); 209 VD1SD->addOperand(*MF, 210 MachineOperand::CreateReg(VirtualDef1, /*isDef*/ true)); 211 VD1SD->addOperand(*MF, 212 MachineOperand::CreateReg(SentinelReg, /*isDef*/ true)); 213 214 auto VD2PU = MF->CreateMachineInstr(MCID, DebugLoc()); 215 VD2PU->addOperand(*MF, 216 MachineOperand::CreateReg(VirtualDef2, /*isDef*/ true)); 217 VD2PU->addOperand(*MF, 218 MachineOperand::CreateReg(PhysicalReg, /*isDef*/ false)); 219 220 auto VD2PD = MF->CreateMachineInstr(MCID, DebugLoc()); 221 VD2PD->addOperand(*MF, 222 MachineOperand::CreateReg(VirtualDef2, /*isDef*/ true)); 223 VD2PD->addOperand(*MF, 224 MachineOperand::CreateReg(PhysicalReg, /*isDef*/ true)); 225 226 checkHashAndIsEqualMatch(VD1VU, VD2VU); 227 checkHashAndIsEqualMatch(VD1VU, VD1SU); 228 checkHashAndIsEqualMatch(VD1VU, VD1SD); 229 checkHashAndIsEqualMatch(VD1VU, VD2PU); 230 checkHashAndIsEqualMatch(VD1VU, VD2PD); 231 232 checkHashAndIsEqualMatch(VD2VU, VD1SU); 233 checkHashAndIsEqualMatch(VD2VU, VD1SD); 234 checkHashAndIsEqualMatch(VD2VU, VD2PU); 235 checkHashAndIsEqualMatch(VD2VU, VD2PD); 236 237 checkHashAndIsEqualMatch(VD1SU, VD1SD); 238 checkHashAndIsEqualMatch(VD1SU, VD2PU); 239 checkHashAndIsEqualMatch(VD1SU, VD2PD); 240 241 checkHashAndIsEqualMatch(VD1SD, VD2PU); 242 checkHashAndIsEqualMatch(VD1SD, VD2PD); 243 244 checkHashAndIsEqualMatch(VD2PU, VD2PD); 245 } 246 } // end namespace 247