1 #include "gtest/gtest.h" 2 #include "llvm/ADT/STLExtras.h" 3 #include "llvm/CodeGen/LiveIntervalAnalysis.h" 4 #include "llvm/CodeGen/MIRParser/MIRParser.h" 5 #include "llvm/CodeGen/MachineFunction.h" 6 #include "llvm/CodeGen/MachineModuleInfo.h" 7 #include "llvm/CodeGen/MachineRegisterInfo.h" 8 #include "llvm/CodeGen/Passes.h" 9 #include "llvm/Support/MemoryBuffer.h" 10 #include "llvm/Support/SourceMgr.h" 11 #include "llvm/Support/TargetRegistry.h" 12 #include "llvm/Support/TargetSelect.h" 13 #include "llvm/Target/TargetMachine.h" 14 #include "llvm/Target/TargetOptions.h" 15 #include "llvm/Target/TargetRegisterInfo.h" 16 #include "llvm/IR/LegacyPassManager.h" 17 18 using namespace llvm; 19 20 namespace llvm { 21 void initializeTestPassPass(PassRegistry &); 22 } 23 24 namespace { 25 26 void initLLVM() { 27 InitializeAllTargets(); 28 InitializeAllTargetMCs(); 29 InitializeAllAsmPrinters(); 30 InitializeAllAsmParsers(); 31 32 PassRegistry *Registry = PassRegistry::getPassRegistry(); 33 initializeCore(*Registry); 34 initializeCodeGen(*Registry); 35 } 36 37 /// Create a TargetMachine. As we lack a dedicated always available target for 38 /// unittests, we go for "x86_64" which should be available in most builds. 39 std::unique_ptr<TargetMachine> createTargetMachine() { 40 Triple TargetTriple("x86_64--"); 41 std::string Error; 42 const Target *T = TargetRegistry::lookupTarget("", TargetTriple, Error); 43 if (!T) 44 return nullptr; 45 46 TargetOptions Options; 47 return std::unique_ptr<TargetMachine>( 48 T->createTargetMachine("x86_64", "", "", Options, None, 49 CodeModel::Default, CodeGenOpt::Aggressive)); 50 } 51 52 std::unique_ptr<Module> parseMIR(LLVMContext &Context, 53 legacy::PassManagerBase &PM, std::unique_ptr<MIRParser> &MIR, 54 const TargetMachine &TM, StringRef MIRCode, const char *FuncName) { 55 SMDiagnostic Diagnostic; 56 std::unique_ptr<MemoryBuffer> MBuffer = MemoryBuffer::getMemBuffer(MIRCode); 57 MIR = createMIRParser(std::move(MBuffer), Context); 58 if (!MIR) 59 return nullptr; 60 61 std::unique_ptr<Module> M = MIR->parseLLVMModule(); 62 if (!M) 63 return nullptr; 64 65 M->setDataLayout(TM.createDataLayout()); 66 67 Function *F = M->getFunction(FuncName); 68 if (!F) 69 return nullptr; 70 71 const LLVMTargetMachine &LLVMTM = static_cast<const LLVMTargetMachine&>(TM); 72 LLVMTM.addMachineModuleInfo(PM); 73 LLVMTM.addMachineFunctionAnalysis(PM, MIR.get()); 74 75 return M; 76 } 77 78 typedef std::function<void(MachineFunction&,LiveIntervals&)> LiveIntervalTest; 79 80 struct TestPass : public MachineFunctionPass { 81 static char ID; 82 TestPass() : MachineFunctionPass(ID) { 83 // We should never call this but always use PM.add(new TestPass(...)) 84 abort(); 85 } 86 TestPass(LiveIntervalTest T) : MachineFunctionPass(ID), T(T) { 87 initializeTestPassPass(*PassRegistry::getPassRegistry()); 88 } 89 90 bool runOnMachineFunction(MachineFunction &MF) override { 91 LiveIntervals &LIS = getAnalysis<LiveIntervals>(); 92 T(MF, LIS); 93 EXPECT_TRUE(MF.verify(this)); 94 return true; 95 } 96 97 void getAnalysisUsage(AnalysisUsage &AU) const override { 98 AU.setPreservesAll(); 99 AU.addRequired<LiveIntervals>(); 100 AU.addPreserved<LiveIntervals>(); 101 MachineFunctionPass::getAnalysisUsage(AU); 102 } 103 private: 104 LiveIntervalTest T; 105 }; 106 107 /** 108 * Move instruction number \p From in front of instruction number \p To and 109 * update affected liveness intervals with LiveIntervalAnalysis::handleMove(). 110 */ 111 static void testHandleMove(MachineFunction &MF, LiveIntervals &LIS, 112 unsigned From, unsigned To, unsigned BlockNum = 0) { 113 MachineBasicBlock &MBB = *MF.getBlockNumbered(BlockNum); 114 115 unsigned I = 0; 116 MachineInstr *FromInstr = nullptr; 117 MachineInstr *ToInstr = nullptr; 118 for (MachineInstr &MI : MBB) { 119 if (I == From) 120 FromInstr = &MI; 121 if (I == To) 122 ToInstr = &MI; 123 ++I; 124 } 125 assert(FromInstr != nullptr && ToInstr != nullptr); 126 127 MBB.splice(ToInstr->getIterator(), &MBB, FromInstr->getIterator()); 128 LIS.handleMove(*FromInstr, true); 129 } 130 131 static void liveIntervalTest(StringRef MIRFunc, LiveIntervalTest T) { 132 LLVMContext Context; 133 std::unique_ptr<TargetMachine> TM = createTargetMachine(); 134 // This test is designed for the X86 backend; stop if it is not available. 135 if (!TM) 136 return; 137 138 legacy::PassManager PM; 139 140 SmallString<160> S; 141 StringRef MIRString = (Twine( 142 "---\n" 143 "...\n" 144 "name: func\n" 145 "registers:\n" 146 " - { id: 0, class: gr64 }\n" 147 "body: |\n" 148 " bb.0:\n" 149 ) + Twine(MIRFunc) + Twine("...\n")).toNullTerminatedStringRef(S); 150 std::unique_ptr<MIRParser> MIR; 151 std::unique_ptr<Module> M = parseMIR(Context, PM, MIR, *TM, MIRString, 152 "func"); 153 154 PM.add(new TestPass(T)); 155 156 PM.run(*M); 157 } 158 159 } // End of anonymous namespace. 160 161 char TestPass::ID = 0; 162 INITIALIZE_PASS(TestPass, "testpass", "testpass", false, false) 163 164 TEST(LiveIntervalTest, MoveUpDef) { 165 // Value defined. 166 liveIntervalTest( 167 " NOOP\n" 168 " NOOP\n" 169 " early-clobber %0 = IMPLICIT_DEF\n" 170 " RETQ %0\n", 171 [](MachineFunction &MF, LiveIntervals &LIS) { 172 testHandleMove(MF, LIS, 2, 1); 173 }); 174 } 175 176 TEST(LiveIntervalTest, MoveUpRedef) { 177 liveIntervalTest( 178 " %0 = IMPLICIT_DEF\n" 179 " NOOP\n" 180 " %0 = IMPLICIT_DEF implicit %0(tied-def 0)\n" 181 " RETQ %0\n", 182 [](MachineFunction &MF, LiveIntervals &LIS) { 183 testHandleMove(MF, LIS, 2, 1); 184 }); 185 } 186 187 TEST(LiveIntervalTest, MoveUpEarlyDef) { 188 liveIntervalTest( 189 " NOOP\n" 190 " NOOP\n" 191 " early-clobber %0 = IMPLICIT_DEF\n" 192 " RETQ %0\n", 193 [](MachineFunction &MF, LiveIntervals &LIS) { 194 testHandleMove(MF, LIS, 2, 1); 195 }); 196 } 197 198 TEST(LiveIntervalTest, MoveUpEarlyRedef) { 199 liveIntervalTest( 200 " %0 = IMPLICIT_DEF\n" 201 " NOOP\n" 202 " early-clobber %0 = IMPLICIT_DEF implicit %0(tied-def 0)\n" 203 " RETQ %0\n", 204 [](MachineFunction &MF, LiveIntervals &LIS) { 205 testHandleMove(MF, LIS, 2, 1); 206 }); 207 } 208 209 TEST(LiveIntervalTest, MoveUpKill) { 210 liveIntervalTest( 211 " %0 = IMPLICIT_DEF\n" 212 " NOOP\n" 213 " NOOP implicit %0\n", 214 [](MachineFunction &MF, LiveIntervals &LIS) { 215 testHandleMove(MF, LIS, 2, 1); 216 }); 217 } 218 219 TEST(LiveIntervalTest, MoveUpKillFollowing) { 220 liveIntervalTest( 221 " %0 = IMPLICIT_DEF\n" 222 " NOOP\n" 223 " NOOP implicit %0\n" 224 " RETQ %0\n", 225 [](MachineFunction &MF, LiveIntervals &LIS) { 226 testHandleMove(MF, LIS, 2, 1); 227 }); 228 } 229 230 // TODO: Construct a situation where we have intervals following a hole 231 // while still having connected components. 232 233 TEST(LiveIntervalTest, MoveDownDef) { 234 // Value defined. 235 liveIntervalTest( 236 " NOOP\n" 237 " early-clobber %0 = IMPLICIT_DEF\n" 238 " NOOP\n" 239 " RETQ %0\n", 240 [](MachineFunction &MF, LiveIntervals &LIS) { 241 testHandleMove(MF, LIS, 1, 2); 242 }); 243 } 244 245 TEST(LiveIntervalTest, MoveDownRedef) { 246 liveIntervalTest( 247 " %0 = IMPLICIT_DEF\n" 248 " %0 = IMPLICIT_DEF implicit %0(tied-def 0)\n" 249 " NOOP\n" 250 " RETQ %0\n", 251 [](MachineFunction &MF, LiveIntervals &LIS) { 252 testHandleMove(MF, LIS, 1, 2); 253 }); 254 } 255 256 TEST(LiveIntervalTest, MoveDownEarlyDef) { 257 liveIntervalTest( 258 " NOOP\n" 259 " early-clobber %0 = IMPLICIT_DEF\n" 260 " NOOP\n" 261 " RETQ %0\n", 262 [](MachineFunction &MF, LiveIntervals &LIS) { 263 testHandleMove(MF, LIS, 1, 2); 264 }); 265 } 266 267 TEST(LiveIntervalTest, MoveDownEarlyRedef) { 268 liveIntervalTest( 269 " %0 = IMPLICIT_DEF\n" 270 " early-clobber %0 = IMPLICIT_DEF implicit %0(tied-def 0)\n" 271 " NOOP\n" 272 " RETQ %0\n", 273 [](MachineFunction &MF, LiveIntervals &LIS) { 274 testHandleMove(MF, LIS, 1, 2); 275 }); 276 } 277 278 TEST(LiveIntervalTest, MoveDownKill) { 279 liveIntervalTest( 280 " %0 = IMPLICIT_DEF\n" 281 " NOOP implicit %0\n" 282 " NOOP\n", 283 [](MachineFunction &MF, LiveIntervals &LIS) { 284 testHandleMove(MF, LIS, 1, 2); 285 }); 286 } 287 288 TEST(LiveIntervalTest, MoveDownKillFollowing) { 289 liveIntervalTest( 290 " %0 = IMPLICIT_DEF\n" 291 " NOOP\n" 292 " NOOP implicit %0\n" 293 " RETQ %0\n", 294 [](MachineFunction &MF, LiveIntervals &LIS) { 295 testHandleMove(MF, LIS, 1, 2); 296 }); 297 } 298 299 TEST(LiveIntervalTest, MoveUndefUse) { 300 liveIntervalTest( 301 " %0 = IMPLICIT_DEF\n" 302 " NOOP implicit undef %0\n" 303 " NOOP implicit %0\n" 304 " NOOP\n", 305 [](MachineFunction &MF, LiveIntervals &LIS) { 306 testHandleMove(MF, LIS, 1, 3); 307 }); 308 } 309 310 TEST(LiveIntervalTest, MoveUpValNos) { 311 // handleMoveUp() had a bug where it would reuse the value number of the 312 // destination segment, even though we have no guarntee that this valno wasn't 313 // used in other segments. 314 liveIntervalTest( 315 " successors: %bb.1, %bb.2\n" 316 " %0 = IMPLICIT_DEF\n" 317 " JG_1 %bb.2, implicit %eflags\n" 318 " JMP_1 %bb.1\n" 319 " bb.2:\n" 320 " NOOP implicit %0\n" 321 " bb.1:\n" 322 " successors: %bb.2\n" 323 " %0 = IMPLICIT_DEF implicit %0(tied-def 0)\n" 324 " %0 = IMPLICIT_DEF implicit %0(tied-def 0)\n" 325 " %0 = IMPLICIT_DEF implicit %0(tied-def 0)\n" 326 " JMP_1 %bb.2\n", 327 [](MachineFunction &MF, LiveIntervals &LIS) { 328 testHandleMove(MF, LIS, 2, 0, 2); 329 }); 330 } 331 332 TEST(LiveIntervalTest, MoveOverUndefUse0) { 333 // findLastUseBefore() used by handleMoveUp() must ignore undef operands. 334 liveIntervalTest( 335 " %0 = IMPLICIT_DEF\n" 336 " NOOP\n" 337 " NOOP implicit undef %0\n" 338 " %0 = IMPLICIT_DEF implicit %0(tied-def 0)\n", 339 [](MachineFunction &MF, LiveIntervals &LIS) { 340 testHandleMove(MF, LIS, 3, 1); 341 }); 342 } 343 344 TEST(LiveIntervalTest, MoveOverUndefUse1) { 345 // findLastUseBefore() used by handleMoveUp() must ignore undef operands. 346 liveIntervalTest( 347 " %rax = IMPLICIT_DEF\n" 348 " NOOP\n" 349 " NOOP implicit undef %rax\n" 350 " %rax = IMPLICIT_DEF implicit %rax(tied-def 0)\n", 351 [](MachineFunction &MF, LiveIntervals &LIS) { 352 testHandleMove(MF, LIS, 3, 1); 353 }); 354 } 355 356 int main(int argc, char **argv) { 357 ::testing::InitGoogleTest(&argc, argv); 358 initLLVM(); 359 return RUN_ALL_TESTS(); 360 } 361