Home | History | Annotate | Download | only in MI
      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