| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 
 | #include "LoongArchSubtarget.h"
#include "LoongArchTargetMachine.h"
#include "llvm/CodeGen/MIRParser/MIRParser.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/TargetSelect.h"
#include <optional>
#include "gtest/gtest.h"
using namespace llvm;
namespace {
std::unique_ptr<LLVMTargetMachine> createTargetMachine() {
  auto TT(Triple::normalize("loongarch64--"));
  std::string CPU("generic-la64");
  std::string FS("+64bit");
  LLVMInitializeLoongArchTargetInfo();
  LLVMInitializeLoongArchTarget();
  LLVMInitializeLoongArchTargetMC();
  std::string Error;
  const Target *TheTarget = TargetRegistry::lookupTarget(TT, Error);
  return std::unique_ptr<LLVMTargetMachine>(static_cast<LLVMTargetMachine *>(
      TheTarget->createTargetMachine(TT, CPU, FS, TargetOptions(), std::nullopt,
                                     std::nullopt, CodeGenOpt::Default)));
}
std::unique_ptr<LoongArchInstrInfo> createInstrInfo(TargetMachine *TM) {
  LoongArchSubtarget ST(TM->getTargetTriple(), std::string(TM->getTargetCPU()),
                        std::string(TM->getTargetCPU()),
                        std::string(TM->getTargetFeatureString()), "lp64d",
                        *TM);
  return std::make_unique<LoongArchInstrInfo>(ST);
}
/// The \p InputIRSnippet is only needed for things that can't be expressed in
/// the \p InputMIRSnippet (global variables etc)
/// Inspired by AArch64
void runChecks(
    LLVMTargetMachine *TM, LoongArchInstrInfo *II,
    const StringRef InputIRSnippet, const StringRef InputMIRSnippet,
    std::function<void(LoongArchInstrInfo &, MachineFunction &)> Checks) {
  LLVMContext Context;
  auto MIRString = "--- |\n"
                   "  declare void @sizes()\n" +
                   InputIRSnippet.str() +
                   "...\n"
                   "---\n"
                   "name: sizes\n"
                   "jumpTable:\n"
                   "  kind:            block-address\n"
                   "  entries:\n"
                   "    - id:              0\n"
                   "      blocks:          [ '%bb.0' ]\n"
                   "body: |\n"
                   "  bb.0:\n" +
                   InputMIRSnippet.str();
  std::unique_ptr<MemoryBuffer> MBuffer = MemoryBuffer::getMemBuffer(MIRString);
  std::unique_ptr<MIRParser> MParser =
      createMIRParser(std::move(MBuffer), Context);
  ASSERT_TRUE(MParser);
  std::unique_ptr<Module> M = MParser->parseIRModule();
  ASSERT_TRUE(M);
  M->setTargetTriple(TM->getTargetTriple().getTriple());
  M->setDataLayout(TM->createDataLayout());
  MachineModuleInfo MMI(TM);
  bool Res = MParser->parseMachineFunctions(*M, MMI);
  ASSERT_FALSE(Res);
  auto F = M->getFunction("sizes");
  ASSERT_TRUE(F != nullptr);
  auto &MF = MMI.getOrCreateMachineFunction(*F);
  Checks(*II, MF);
}
} // anonymous namespace
TEST(InstSizes, INLINEASM_BR) {
  std::unique_ptr<LLVMTargetMachine> TM = createTargetMachine();
  std::unique_ptr<LoongArchInstrInfo> II = createInstrInfo(TM.get());
  runChecks(TM.get(), II.get(), "",
            // clang-format off
            "  INLINEASM_BR &nop, 1 /* sideeffect attdialect */, 13 /* imm */, %jump-table.0\n",
            // clang-format on
            [](LoongArchInstrInfo &II, MachineFunction &MF) {
              auto I = MF.begin()->begin();
              EXPECT_EQ(4u, II.getInstSizeInBytes(*I));
            });
}
TEST(InstSizes, SPACE) {
  std::unique_ptr<LLVMTargetMachine> TM = createTargetMachine();
  std::unique_ptr<LoongArchInstrInfo> II = createInstrInfo(TM.get());
  runChecks(TM.get(), II.get(), "", "  INLINEASM &\".space 1024\", 1\n",
            [](LoongArchInstrInfo &II, MachineFunction &MF) {
              auto I = MF.begin()->begin();
              EXPECT_EQ(1024u, II.getInstSizeInBytes(*I));
            });
}
TEST(InstSizes, AtomicPseudo) {
  std::unique_ptr<LLVMTargetMachine> TM = createTargetMachine();
  std::unique_ptr<LoongArchInstrInfo> II = createInstrInfo(TM.get());
  runChecks(
      TM.get(), II.get(), "",
      // clang-format off
      "    dead early-clobber renamable $r10, dead early-clobber renamable $r11 = PseudoMaskedAtomicLoadAdd32 renamable $r7, renamable $r6, renamable $r8, 4\n"
      "    dead early-clobber renamable $r10, dead early-clobber renamable $r11 = PseudoAtomicLoadAdd32 renamable $r7, renamable $r6, renamable $r8\n"
      "    dead early-clobber renamable $r5, dead early-clobber renamable $r9, dead early-clobber renamable $r10 = PseudoMaskedAtomicLoadUMax32 renamable $r7, renamable $r6, renamable $r8, 4\n"
      "    early-clobber renamable $r9, dead early-clobber renamable $r10, dead early-clobber renamable $r11 = PseudoMaskedAtomicLoadMax32 killed renamable $r6, killed renamable $r5, killed renamable $r7, killed renamable $r8, 4\n"
      "    dead early-clobber renamable $r5, dead early-clobber renamable $r9 = PseudoCmpXchg32 renamable $r7, renamable $r4, renamable $r6\n"
      "    dead early-clobber renamable $r5, dead early-clobber renamable $r9 = PseudoMaskedCmpXchg32 killed renamable $r7, killed renamable $r4, killed renamable $r6, killed renamable $r8, 4\n",
      // clang-format on
      [](LoongArchInstrInfo &II, MachineFunction &MF) {
        auto I = MF.begin()->begin();
        EXPECT_EQ(36u, II.getInstSizeInBytes(*I));
        ++I;
        EXPECT_EQ(24u, II.getInstSizeInBytes(*I));
        ++I;
        EXPECT_EQ(48u, II.getInstSizeInBytes(*I));
        ++I;
        EXPECT_EQ(56u, II.getInstSizeInBytes(*I));
        ++I;
        EXPECT_EQ(36u, II.getInstSizeInBytes(*I));
        ++I;
        EXPECT_EQ(44u, II.getInstSizeInBytes(*I));
      });
}
 |