1 #include "AArch64InstrInfo.h"
2 #include "AArch64Subtarget.h"
3 #include "AArch64TargetMachine.h"
4 #include "llvm/MC/MCSubtargetInfo.h"
5 #include "llvm/MC/TargetRegistry.h"
6 #include "llvm/Support/TargetSelect.h"
7 #include "llvm/Support/raw_ostream.h"
8 #include "llvm/Target/TargetMachine.h"
9 #include "llvm/Target/TargetOptions.h"
11 #include "gtest/gtest.h"
13 #define GET_COMPUTE_FEATURES
14 #include "AArch64GenInstrInfo.inc"
18 std::unique_ptr
<TargetMachine
> createTargetMachine(const std::string
&CPU
) {
19 auto TT(Triple::normalize("aarch64--"));
21 LLVMInitializeAArch64TargetInfo();
22 LLVMInitializeAArch64Target();
23 LLVMInitializeAArch64TargetMC();
26 const Target
*TheTarget
= TargetRegistry::lookupTarget(TT
, Error
);
28 return std::unique_ptr
<TargetMachine
>(
29 TheTarget
->createTargetMachine(TT
, CPU
, "", TargetOptions(), std::nullopt
,
30 std::nullopt
, CodeGenOptLevel::Default
));
33 std::unique_ptr
<AArch64InstrInfo
> createInstrInfo(TargetMachine
*TM
) {
34 AArch64Subtarget
ST(TM
->getTargetTriple(), std::string(TM
->getTargetCPU()),
35 std::string(TM
->getTargetCPU()),
36 std::string(TM
->getTargetFeatureString()), *TM
, true);
37 return std::make_unique
<AArch64InstrInfo
>(ST
);
40 /// Returns true if the instruction is enabled under a feature that the
42 static bool isInstructionSupportedByCPU(unsigned Opcode
,
43 FeatureBitset Features
) {
44 FeatureBitset AvailableFeatures
=
45 llvm::AArch64_MC::computeAvailableFeatures(Features
);
46 FeatureBitset RequiredFeatures
=
47 llvm::AArch64_MC::computeRequiredFeatures(Opcode
);
48 FeatureBitset MissingFeatures
=
49 (AvailableFeatures
& RequiredFeatures
) ^ RequiredFeatures
;
50 return MissingFeatures
.none();
53 void runSVEPseudoTestForCPU(const std::string
&CPU
) {
55 std::unique_ptr
<TargetMachine
> TM
= createTargetMachine(CPU
);
57 std::unique_ptr
<AArch64InstrInfo
> II
= createInstrInfo(TM
.get());
60 const MCSubtargetInfo
*STI
= TM
->getMCSubtargetInfo();
61 MCSchedModel SchedModel
= STI
->getSchedModel();
63 for (unsigned i
= 0; i
< AArch64::INSTRUCTION_LIST_END
; ++i
) {
64 // Check if instruction is in the pseudo table
65 // i holds the opcode of the pseudo, OrigInstr holds the opcode of the
66 // original instruction
67 int OrigInstr
= AArch64::getSVEPseudoMap(i
);
71 // Ignore any pseudos/instructions which may not be part of the scheduler
72 // model for the CPU we're testing. This avoids this test from failing when
73 // new instructions are added that are not yet covered by the scheduler
75 if (!isInstructionSupportedByCPU(OrigInstr
, STI
->getFeatureBits()))
78 const MCInstrDesc
&Desc
= II
->get(i
);
79 unsigned SCClass
= Desc
.getSchedClass();
80 const MCSchedClassDesc
*SCDesc
= SchedModel
.getSchedClassDesc(SCClass
);
82 const MCInstrDesc
&DescOrig
= II
->get(OrigInstr
);
83 unsigned SCClassOrig
= DescOrig
.getSchedClass();
84 const MCSchedClassDesc
*SCDescOrig
=
85 SchedModel
.getSchedClassDesc(SCClassOrig
);
90 for (unsigned DefIdx
= 0, DefEnd
= SCDesc
->NumWriteLatencyEntries
;
91 DefIdx
!= DefEnd
; ++DefIdx
) {
92 const MCWriteLatencyEntry
*WLEntry
=
93 STI
->getWriteLatencyEntry(SCDesc
, DefIdx
);
94 const MCWriteLatencyEntry
*WLEntryOrig
=
95 STI
->getWriteLatencyEntry(SCDescOrig
, DefIdx
);
96 Latency
= std::max(Latency
, static_cast<int>(WLEntry
->Cycles
));
97 LatencyOrig
= std::max(Latency
, static_cast<int>(WLEntryOrig
->Cycles
));
100 ASSERT_EQ(Latency
, LatencyOrig
);
101 ASSERT_TRUE(SCDesc
->isValid());
105 // TODO : Add more CPUs that support SVE/SVE2
106 TEST(AArch64SVESchedPseudoTesta510
, IsCorrect
) {
107 runSVEPseudoTestForCPU("cortex-a510");
110 TEST(AArch64SVESchedPseudoTestn1
, IsCorrect
) {
111 runSVEPseudoTestForCPU("neoverse-n2");
114 TEST(AArch64SVESchedPseudoTestn3
, IsCorrect
) {
115 runSVEPseudoTestForCPU("neoverse-n3");
118 TEST(AArch64SVESchedPseudoTestv1
, IsCorrect
) {
119 runSVEPseudoTestForCPU("neoverse-v1");
122 TEST(AArch64SVESchedPseudoTestv2
, IsCorrect
) {
123 runSVEPseudoTestForCPU("neoverse-v2");