1 #include "RegisterAliasing.h"
2 
3 #include <cassert>
4 #include <memory>
5 
6 #include "X86InstrInfo.h"
7 #include "llvm/Support/TargetRegistry.h"
8 #include "llvm/Support/TargetSelect.h"
9 #include "gmock/gmock.h"
10 #include "gtest/gtest.h"
11 
12 namespace exegesis {
13 namespace {
14 
15 class RegisterAliasingTest : public ::testing::Test {
16 protected:
RegisterAliasingTest()17   RegisterAliasingTest() {
18     const std::string TT = "x86_64-unknown-linux";
19     std::string error;
20     const llvm::Target *const TheTarget =
21         llvm::TargetRegistry::lookupTarget(TT, error);
22     if (!TheTarget) {
23       llvm::errs() << error << "\n";
24       return;
25     }
26     MCRegInfo.reset(TheTarget->createMCRegInfo(TT));
27   }
28 
SetUpTestCase()29   static void SetUpTestCase() {
30     LLVMInitializeX86TargetInfo();
31     LLVMInitializeX86Target();
32     LLVMInitializeX86TargetMC();
33   }
34 
getMCRegInfo()35   const llvm::MCRegisterInfo &getMCRegInfo() {
36     assert(MCRegInfo);
37     return *MCRegInfo;
38   }
39 
40 private:
41   std::unique_ptr<const llvm::MCRegisterInfo> MCRegInfo;
42 };
43 
TEST_F(RegisterAliasingTest,TrackSimpleRegister)44 TEST_F(RegisterAliasingTest, TrackSimpleRegister) {
45   const auto &RegInfo = getMCRegInfo();
46   const RegisterAliasingTracker tracker(RegInfo, llvm::X86::EAX);
47   std::set<llvm::MCPhysReg> ActualAliasedRegisters;
48   for (unsigned I : tracker.aliasedBits().set_bits())
49     ActualAliasedRegisters.insert(static_cast<llvm::MCPhysReg>(I));
50   const std::set<llvm::MCPhysReg> ExpectedAliasedRegisters = {
51       llvm::X86::AL,  llvm::X86::AH,  llvm::X86::AX,
52       llvm::X86::EAX, llvm::X86::HAX, llvm::X86::RAX};
53   ASSERT_THAT(ActualAliasedRegisters, ExpectedAliasedRegisters);
54   for (llvm::MCPhysReg aliased : ExpectedAliasedRegisters) {
55     ASSERT_THAT(tracker.getOrigin(aliased), llvm::X86::EAX);
56   }
57 }
58 
TEST_F(RegisterAliasingTest,TrackRegisterClass)59 TEST_F(RegisterAliasingTest, TrackRegisterClass) {
60   // The alias bits for GR8_ABCD_LRegClassID are the union of the alias bits for
61   // AL, BL, CL and DL.
62   const auto &RegInfo = getMCRegInfo();
63   const llvm::BitVector NoReservedReg(RegInfo.getNumRegs());
64 
65   const RegisterAliasingTracker RegClassTracker(
66       RegInfo, NoReservedReg,
67       RegInfo.getRegClass(llvm::X86::GR8_ABCD_LRegClassID));
68 
69   llvm::BitVector sum(RegInfo.getNumRegs());
70   sum |= RegisterAliasingTracker(RegInfo, llvm::X86::AL).aliasedBits();
71   sum |= RegisterAliasingTracker(RegInfo, llvm::X86::BL).aliasedBits();
72   sum |= RegisterAliasingTracker(RegInfo, llvm::X86::CL).aliasedBits();
73   sum |= RegisterAliasingTracker(RegInfo, llvm::X86::DL).aliasedBits();
74 
75   ASSERT_THAT(RegClassTracker.aliasedBits(), sum);
76 }
77 
TEST_F(RegisterAliasingTest,TrackRegisterClassCache)78 TEST_F(RegisterAliasingTest, TrackRegisterClassCache) {
79   // Fetching twice the same tracker yields the same pointers.
80   const auto &RegInfo = getMCRegInfo();
81   const llvm::BitVector NoReservedReg(RegInfo.getNumRegs());
82   RegisterAliasingTrackerCache Cache(RegInfo, NoReservedReg);
83   ASSERT_THAT(&Cache.getRegister(llvm::X86::AX),
84               &Cache.getRegister(llvm::X86::AX));
85 
86   ASSERT_THAT(&Cache.getRegisterClass(llvm::X86::GR8_ABCD_LRegClassID),
87               &Cache.getRegisterClass(llvm::X86::GR8_ABCD_LRegClassID));
88 }
89 
90 } // namespace
91 } // namespace exegesis
92