Skip to content

Commit

Permalink
[LoongArch] Use tablegen size for getInstSizeInBytes
Browse files Browse the repository at this point in the history
Correct the pseudo atomic instruction size for branch
relaxation and branch folding passes.

Inspired by D118175, D118009 and D117970.

Depends on D138481

Reviewed By: SixWeining, gonglingqin, xen0n

Differential Revision: https://reviews.llvm.org/D138469
  • Loading branch information
XiaodongLoong committed Dec 3, 2022
1 parent f64d4a2 commit d62480c
Show file tree
Hide file tree
Showing 4 changed files with 175 additions and 1 deletion.
5 changes: 4 additions & 1 deletion llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
Expand Up @@ -176,7 +176,10 @@ void LoongArchInstrInfo::movImm(MachineBasicBlock &MBB,
}

unsigned LoongArchInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
if (MI.getOpcode() == TargetOpcode::INLINEASM) {
unsigned Opcode = MI.getOpcode();

if (Opcode == TargetOpcode::INLINEASM ||
Opcode == TargetOpcode::INLINEASM_BR) {
const MachineFunction *MF = MI.getParent()->getParent();
const MCAsmInfo *MAI = MF->getTarget().getMCAsmInfo();
return getInlineAsmLength(MI.getOperand(0).getSymbolName(), *MAI);
Expand Down
6 changes: 6 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
Expand Up @@ -1302,6 +1302,7 @@ class PseudoMaskedAM
let mayLoad = 1;
let mayStore = 1;
let hasSideEffects = 0;
let Size = 36;
}

def PseudoMaskedAtomicSwap32 : PseudoMaskedAM;
Expand All @@ -1315,6 +1316,7 @@ class PseudoAM : Pseudo<(outs GPR:$res, GPR:$scratch),
let mayLoad = 1;
let mayStore = 1;
let hasSideEffects = 0;
let Size = 24;
}

def PseudoAtomicSwap32 : PseudoAM;
Expand Down Expand Up @@ -1347,6 +1349,7 @@ class PseudoMaskedAMUMinUMax
let mayLoad = 1;
let mayStore = 1;
let hasSideEffects = 0;
let Size = 48;
}

def PseudoMaskedAtomicLoadUMax32 : PseudoMaskedAMUMinUMax;
Expand All @@ -1361,6 +1364,7 @@ class PseudoMaskedAMMinMax
let mayLoad = 1;
let mayStore = 1;
let hasSideEffects = 0;
let Size = 56;
}

def PseudoMaskedAtomicLoadMax32 : PseudoMaskedAMMinMax;
Expand All @@ -1375,6 +1379,7 @@ class PseudoCmpXchg
let mayLoad = 1;
let mayStore = 1;
let hasSideEffects = 0;
let Size = 36;
}

def PseudoCmpXchg32 : PseudoCmpXchg;
Expand All @@ -1388,6 +1393,7 @@ def PseudoMaskedCmpXchg32
let mayLoad = 1;
let mayStore = 1;
let hasSideEffects = 0;
let Size = 44;
}

class PseudoMaskedAMMinMaxPat<Intrinsic intrin, Pseudo AMInst>
Expand Down
25 changes: 25 additions & 0 deletions llvm/unittests/Target/LoongArch/CMakeLists.txt
@@ -0,0 +1,25 @@
include_directories(
${LLVM_MAIN_SRC_DIR}/lib/Target/LoongArch
${LLVM_BINARY_DIR}/lib/Target/LoongArch
)

set(LLVM_LINK_COMPONENTS
AsmParser
CodeGen
Core
GlobalISel
LoongArchCodeGen
LoongArchDesc
LoongArchInfo
MC
MIRParser
SelectionDAG
Support
Target
)

add_llvm_target_unittest(LoongArchTests
InstSizes.cpp
)

set_property(TARGET LoongArchTests PROPERTY FOLDER "Tests/UnitTests/TargetTests")
140 changes: 140 additions & 0 deletions llvm/unittests/Target/LoongArch/InstSizes.cpp
@@ -0,0 +1,140 @@
#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 "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(), None, None, 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\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));
});
}

0 comments on commit d62480c

Please sign in to comment.