1 2 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
|
#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<TargetMachine> 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<TargetMachine>(
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<TargetMachine> 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(AArch64SVESchedPseudoTestn3, IsCorrect) {
runSVEPseudoTestForCPU("neoverse-n3");
}
TEST(AArch64SVESchedPseudoTestv1, IsCorrect) {
runSVEPseudoTestForCPU("neoverse-v1");
}
TEST(AArch64SVESchedPseudoTestv2, IsCorrect) {
runSVEPseudoTestForCPU("neoverse-v2");
}
} // namespace
|