[LoongArch] Use tablegen size for getInstSizeInBytes
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
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -1302,6 +1302,7 @@ class PseudoMaskedAM
|
||||
let mayLoad = 1;
|
||||
let mayStore = 1;
|
||||
let hasSideEffects = 0;
|
||||
let Size = 36;
|
||||
}
|
||||
|
||||
def PseudoMaskedAtomicSwap32 : PseudoMaskedAM;
|
||||
@@ -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;
|
||||
@@ -1347,6 +1349,7 @@ class PseudoMaskedAMUMinUMax
|
||||
let mayLoad = 1;
|
||||
let mayStore = 1;
|
||||
let hasSideEffects = 0;
|
||||
let Size = 48;
|
||||
}
|
||||
|
||||
def PseudoMaskedAtomicLoadUMax32 : PseudoMaskedAMUMinUMax;
|
||||
@@ -1361,6 +1364,7 @@ class PseudoMaskedAMMinMax
|
||||
let mayLoad = 1;
|
||||
let mayStore = 1;
|
||||
let hasSideEffects = 0;
|
||||
let Size = 56;
|
||||
}
|
||||
|
||||
def PseudoMaskedAtomicLoadMax32 : PseudoMaskedAMMinMax;
|
||||
@@ -1375,6 +1379,7 @@ class PseudoCmpXchg
|
||||
let mayLoad = 1;
|
||||
let mayStore = 1;
|
||||
let hasSideEffects = 0;
|
||||
let Size = 36;
|
||||
}
|
||||
|
||||
def PseudoCmpXchg32 : PseudoCmpXchg;
|
||||
@@ -1388,6 +1393,7 @@ def PseudoMaskedCmpXchg32
|
||||
let mayLoad = 1;
|
||||
let mayStore = 1;
|
||||
let hasSideEffects = 0;
|
||||
let Size = 44;
|
||||
}
|
||||
|
||||
class PseudoMaskedAMMinMaxPat<Intrinsic intrin, Pseudo AMInst>
|
||||
|
||||
25
llvm/unittests/Target/LoongArch/CMakeLists.txt
Normal file
25
llvm/unittests/Target/LoongArch/CMakeLists.txt
Normal file
@@ -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
llvm/unittests/Target/LoongArch/InstSizes.cpp
Normal file
140
llvm/unittests/Target/LoongArch/InstSizes.cpp
Normal file
@@ -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));
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user