Similar to #84187, this enables the existing test we have for checking the scheduling info of the pseudos matches the real instructions, and adjusts the scheduling info in the NeoverseN2 model to make sure all cases were handled.
123 lines
4.1 KiB
C++
123 lines
4.1 KiB
C++
#include "AArch64InstrInfo.h"
|
|
#include "AArch64Subtarget.h"
|
|
#include "AArch64TargetMachine.h"
|
|
#include "llvm/MC/MCSubtargetInfo.h"
|
|
#include "llvm/MC/TargetRegistry.h"
|
|
#include "llvm/Support/TargetSelect.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
#include "llvm/Target/TargetMachine.h"
|
|
#include "llvm/Target/TargetOptions.h"
|
|
|
|
#include "gtest/gtest.h"
|
|
|
|
#define GET_COMPUTE_FEATURES
|
|
#include "AArch64GenInstrInfo.inc"
|
|
|
|
using namespace llvm;
|
|
namespace {
|
|
std::unique_ptr<LLVMTargetMachine> createTargetMachine(const std::string &CPU) {
|
|
auto TT(Triple::normalize("aarch64--"));
|
|
|
|
LLVMInitializeAArch64TargetInfo();
|
|
LLVMInitializeAArch64Target();
|
|
LLVMInitializeAArch64TargetMC();
|
|
|
|
std::string Error;
|
|
const Target *TheTarget = TargetRegistry::lookupTarget(TT, Error);
|
|
|
|
return std::unique_ptr<LLVMTargetMachine>(static_cast<LLVMTargetMachine *>(
|
|
TheTarget->createTargetMachine(TT, CPU, "", TargetOptions(), std::nullopt,
|
|
std::nullopt, CodeGenOptLevel::Default)));
|
|
}
|
|
|
|
std::unique_ptr<AArch64InstrInfo> createInstrInfo(TargetMachine *TM) {
|
|
AArch64Subtarget ST(TM->getTargetTriple(), std::string(TM->getTargetCPU()),
|
|
std::string(TM->getTargetCPU()),
|
|
std::string(TM->getTargetFeatureString()), *TM, true);
|
|
return std::make_unique<AArch64InstrInfo>(ST);
|
|
}
|
|
|
|
/// Returns true if the instruction is enabled under a feature that the
|
|
/// CPU supports.
|
|
static bool isInstructionSupportedByCPU(unsigned Opcode,
|
|
FeatureBitset Features) {
|
|
FeatureBitset AvailableFeatures =
|
|
llvm::AArch64_MC::computeAvailableFeatures(Features);
|
|
FeatureBitset RequiredFeatures =
|
|
llvm::AArch64_MC::computeRequiredFeatures(Opcode);
|
|
FeatureBitset MissingFeatures =
|
|
(AvailableFeatures & RequiredFeatures) ^ RequiredFeatures;
|
|
return MissingFeatures.none();
|
|
}
|
|
|
|
void runSVEPseudoTestForCPU(const std::string &CPU) {
|
|
|
|
std::unique_ptr<LLVMTargetMachine> TM = createTargetMachine(CPU);
|
|
ASSERT_TRUE(TM);
|
|
std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get());
|
|
ASSERT_TRUE(II);
|
|
|
|
const MCSubtargetInfo *STI = TM->getMCSubtargetInfo();
|
|
MCSchedModel SchedModel = STI->getSchedModel();
|
|
|
|
for (unsigned i = 0; i < AArch64::INSTRUCTION_LIST_END; ++i) {
|
|
// Check if instruction is in the pseudo table
|
|
// i holds the opcode of the pseudo, OrigInstr holds the opcode of the
|
|
// original instruction
|
|
int OrigInstr = AArch64::getSVEPseudoMap(i);
|
|
if (OrigInstr == -1)
|
|
continue;
|
|
|
|
// Ignore any pseudos/instructions which may not be part of the scheduler
|
|
// model for the CPU we're testing. This avoids this test from failing when
|
|
// new instructions are added that are not yet covered by the scheduler
|
|
// model.
|
|
if (!isInstructionSupportedByCPU(OrigInstr, STI->getFeatureBits()))
|
|
continue;
|
|
|
|
const MCInstrDesc &Desc = II->get(i);
|
|
unsigned SCClass = Desc.getSchedClass();
|
|
const MCSchedClassDesc *SCDesc = SchedModel.getSchedClassDesc(SCClass);
|
|
|
|
const MCInstrDesc &DescOrig = II->get(OrigInstr);
|
|
unsigned SCClassOrig = DescOrig.getSchedClass();
|
|
const MCSchedClassDesc *SCDescOrig =
|
|
SchedModel.getSchedClassDesc(SCClassOrig);
|
|
|
|
int Latency = 0;
|
|
int LatencyOrig = 0;
|
|
|
|
for (unsigned DefIdx = 0, DefEnd = SCDesc->NumWriteLatencyEntries;
|
|
DefIdx != DefEnd; ++DefIdx) {
|
|
const MCWriteLatencyEntry *WLEntry =
|
|
STI->getWriteLatencyEntry(SCDesc, DefIdx);
|
|
const MCWriteLatencyEntry *WLEntryOrig =
|
|
STI->getWriteLatencyEntry(SCDescOrig, DefIdx);
|
|
Latency = std::max(Latency, static_cast<int>(WLEntry->Cycles));
|
|
LatencyOrig = std::max(Latency, static_cast<int>(WLEntryOrig->Cycles));
|
|
}
|
|
|
|
ASSERT_EQ(Latency, LatencyOrig);
|
|
ASSERT_TRUE(SCDesc->isValid());
|
|
}
|
|
}
|
|
|
|
// TODO : Add more CPUs that support SVE/SVE2
|
|
TEST(AArch64SVESchedPseudoTesta510, IsCorrect) {
|
|
runSVEPseudoTestForCPU("cortex-a510");
|
|
}
|
|
|
|
TEST(AArch64SVESchedPseudoTestn1, IsCorrect) {
|
|
runSVEPseudoTestForCPU("neoverse-n2");
|
|
}
|
|
|
|
TEST(AArch64SVESchedPseudoTestv1, IsCorrect) {
|
|
runSVEPseudoTestForCPU("neoverse-v1");
|
|
}
|
|
|
|
TEST(AArch64SVESchedPseudoTestv2, IsCorrect) {
|
|
runSVEPseudoTestForCPU("neoverse-v2");
|
|
}
|
|
|
|
} // namespace
|