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" 10 11 #include "gtest/gtest.h" 12 13 #define GET_COMPUTE_FEATURES 14 #include "AArch64GenInstrInfo.inc" 15 16 using namespace llvm; 17 namespace { 18 std::unique_ptr<TargetMachine> createTargetMachine(const std::string &CPU) { 19 auto TT(Triple::normalize("aarch64--")); 20 21 LLVMInitializeAArch64TargetInfo(); 22 LLVMInitializeAArch64Target(); 23 LLVMInitializeAArch64TargetMC(); 24 25 std::string Error; 26 const Target *TheTarget = TargetRegistry::lookupTarget(TT, Error); 27 28 return std::unique_ptr<TargetMachine>( 29 TheTarget->createTargetMachine(TT, CPU, "", TargetOptions(), std::nullopt, 30 std::nullopt, CodeGenOptLevel::Default)); 31 } 32 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); 38 } 39 40 /// Returns true if the instruction is enabled under a feature that the 41 /// CPU supports. 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(); 51 } 52 53 void runSVEPseudoTestForCPU(const std::string &CPU) { 54 55 std::unique_ptr<TargetMachine> TM = createTargetMachine(CPU); 56 ASSERT_TRUE(TM); 57 std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get()); 58 ASSERT_TRUE(II); 59 60 const MCSubtargetInfo *STI = TM->getMCSubtargetInfo(); 61 MCSchedModel SchedModel = STI->getSchedModel(); 62 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); 68 if (OrigInstr == -1) 69 continue; 70 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 74 // model. 75 if (!isInstructionSupportedByCPU(OrigInstr, STI->getFeatureBits())) 76 continue; 77 78 const MCInstrDesc &Desc = II->get(i); 79 unsigned SCClass = Desc.getSchedClass(); 80 const MCSchedClassDesc *SCDesc = SchedModel.getSchedClassDesc(SCClass); 81 82 const MCInstrDesc &DescOrig = II->get(OrigInstr); 83 unsigned SCClassOrig = DescOrig.getSchedClass(); 84 const MCSchedClassDesc *SCDescOrig = 85 SchedModel.getSchedClassDesc(SCClassOrig); 86 87 int Latency = 0; 88 int LatencyOrig = 0; 89 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)); 98 } 99 100 ASSERT_EQ(Latency, LatencyOrig); 101 ASSERT_TRUE(SCDesc->isValid()); 102 } 103 } 104 105 // TODO : Add more CPUs that support SVE/SVE2 106 TEST(AArch64SVESchedPseudoTesta510, IsCorrect) { 107 runSVEPseudoTestForCPU("cortex-a510"); 108 } 109 110 TEST(AArch64SVESchedPseudoTestn1, IsCorrect) { 111 runSVEPseudoTestForCPU("neoverse-n2"); 112 } 113 114 TEST(AArch64SVESchedPseudoTestn3, IsCorrect) { 115 runSVEPseudoTestForCPU("neoverse-n3"); 116 } 117 118 TEST(AArch64SVESchedPseudoTestv1, IsCorrect) { 119 runSVEPseudoTestForCPU("neoverse-v1"); 120 } 121 122 TEST(AArch64SVESchedPseudoTestv2, IsCorrect) { 123 runSVEPseudoTestForCPU("neoverse-v2"); 124 } 125 126 } // namespace 127