106c3fb27SDimitry Andric //===-- RISCVSubtarget.cpp - RISC-V Subtarget Information -----------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 906c3fb27SDimitry Andric // This file implements the RISC-V specific subclass of TargetSubtargetInfo. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "RISCVSubtarget.h" 1406c3fb27SDimitry Andric #include "GISel/RISCVCallLowering.h" 1506c3fb27SDimitry Andric #include "GISel/RISCVLegalizerInfo.h" 160b57cec5SDimitry Andric #include "RISCV.h" 170b57cec5SDimitry Andric #include "RISCVFrameLowering.h" 188bcb0991SDimitry Andric #include "RISCVTargetMachine.h" 19b3edf446SDimitry Andric #include "llvm/CodeGen/MacroFusion.h" 20b3edf446SDimitry Andric #include "llvm/CodeGen/ScheduleDAGMutation.h" 21349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h" 2204eeddc0SDimitry Andric #include "llvm/Support/ErrorHandling.h" 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric using namespace llvm; 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric #define DEBUG_TYPE "riscv-subtarget" 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric #define GET_SUBTARGETINFO_TARGET_DESC 290b57cec5SDimitry Andric #define GET_SUBTARGETINFO_CTOR 300b57cec5SDimitry Andric #include "RISCVGenSubtargetInfo.inc" 310b57cec5SDimitry Andric 32b3edf446SDimitry Andric #define GET_RISCV_MACRO_FUSION_PRED_IMPL 33b3edf446SDimitry Andric #include "RISCVGenMacroFusion.inc" 34b3edf446SDimitry Andric 355f757f3fSDimitry Andric namespace llvm::RISCVTuneInfoTable { 365f757f3fSDimitry Andric 375f757f3fSDimitry Andric #define GET_RISCVTuneInfoTable_IMPL 385f757f3fSDimitry Andric #include "RISCVGenSearchableTables.inc" 395f757f3fSDimitry Andric } // namespace llvm::RISCVTuneInfoTable 405f757f3fSDimitry Andric 41fe6060f1SDimitry Andric static cl::opt<unsigned> RVVVectorLMULMax( 42fe6060f1SDimitry Andric "riscv-v-fixed-length-vector-lmul-max", 43fe6060f1SDimitry Andric cl::desc("The maximum LMUL value to use for fixed length vectors. " 44fe6060f1SDimitry Andric "Fractional LMUL values are not supported."), 45fe6060f1SDimitry Andric cl::init(8), cl::Hidden); 46fe6060f1SDimitry Andric 4704eeddc0SDimitry Andric static cl::opt<bool> RISCVDisableUsingConstantPoolForLargeInts( 4804eeddc0SDimitry Andric "riscv-disable-using-constant-pool-for-large-ints", 4904eeddc0SDimitry Andric cl::desc("Disable using constant pool for large integers."), 5004eeddc0SDimitry Andric cl::init(false), cl::Hidden); 5104eeddc0SDimitry Andric 5204eeddc0SDimitry Andric static cl::opt<unsigned> RISCVMaxBuildIntsCost( 5304eeddc0SDimitry Andric "riscv-max-build-ints-cost", 5404eeddc0SDimitry Andric cl::desc("The maximum cost used for building integers."), cl::init(0), 5504eeddc0SDimitry Andric cl::Hidden); 5604eeddc0SDimitry Andric 575f757f3fSDimitry Andric static cl::opt<bool> UseAA("riscv-use-aa", cl::init(true), 585f757f3fSDimitry Andric cl::desc("Enable the use of AA during codegen.")); 595f757f3fSDimitry Andric 605f757f3fSDimitry Andric static cl::opt<unsigned> RISCVMinimumJumpTableEntries( 615f757f3fSDimitry Andric "riscv-min-jump-table-entries", cl::Hidden, 625f757f3fSDimitry Andric cl::desc("Set minimum number of entries to use a jump table on RISCV")); 635f757f3fSDimitry Andric 640b57cec5SDimitry Andric void RISCVSubtarget::anchor() {} 650b57cec5SDimitry Andric 66fe6060f1SDimitry Andric RISCVSubtarget & 67fe6060f1SDimitry Andric RISCVSubtarget::initializeSubtargetDependencies(const Triple &TT, StringRef CPU, 68fe6060f1SDimitry Andric StringRef TuneCPU, StringRef FS, 69fe6060f1SDimitry Andric StringRef ABIName) { 700b57cec5SDimitry Andric // Determine default and user-specified characteristics 710b57cec5SDimitry Andric bool Is64Bit = TT.isArch64Bit(); 7281ad6265SDimitry Andric if (CPU.empty() || CPU == "generic") 73fe6060f1SDimitry Andric CPU = Is64Bit ? "generic-rv64" : "generic-rv32"; 74fe6060f1SDimitry Andric 75fe6060f1SDimitry Andric if (TuneCPU.empty()) 76fe6060f1SDimitry Andric TuneCPU = CPU; 77fe6060f1SDimitry Andric 785f757f3fSDimitry Andric TuneInfo = RISCVTuneInfoTable::getRISCVTuneInfo(TuneCPU); 795f757f3fSDimitry Andric // If there is no TuneInfo for this CPU, we fail back to generic. 805f757f3fSDimitry Andric if (!TuneInfo) 815f757f3fSDimitry Andric TuneInfo = RISCVTuneInfoTable::getRISCVTuneInfo("generic"); 825f757f3fSDimitry Andric assert(TuneInfo && "TuneInfo shouldn't be nullptr!"); 830b57cec5SDimitry Andric 845f757f3fSDimitry Andric ParseSubtargetFeatures(CPU, TuneCPU, FS); 850b57cec5SDimitry Andric TargetABI = RISCVABI::computeTargetABI(TT, getFeatureBits(), ABIName); 860b57cec5SDimitry Andric RISCVFeatures::validate(TT, getFeatureBits()); 870b57cec5SDimitry Andric return *this; 880b57cec5SDimitry Andric } 890b57cec5SDimitry Andric 90e8d8bef9SDimitry Andric RISCVSubtarget::RISCVSubtarget(const Triple &TT, StringRef CPU, 91e8d8bef9SDimitry Andric StringRef TuneCPU, StringRef FS, 92bdd1243dSDimitry Andric StringRef ABIName, unsigned RVVVectorBitsMin, 93bdd1243dSDimitry Andric unsigned RVVVectorBitsMax, 94bdd1243dSDimitry Andric const TargetMachine &TM) 95e8d8bef9SDimitry Andric : RISCVGenSubtargetInfo(TT, CPU, TuneCPU, FS), 96bdd1243dSDimitry Andric RVVVectorBitsMin(RVVVectorBitsMin), RVVVectorBitsMax(RVVVectorBitsMax), 97bdd1243dSDimitry Andric FrameLowering( 98bdd1243dSDimitry Andric initializeSubtargetDependencies(TT, CPU, TuneCPU, FS, ABIName)), 99*0fca6ea1SDimitry Andric InstrInfo(*this), RegInfo(getHwMode()), TLInfo(TM, *this) {} 1008bcb0991SDimitry Andric 1018bcb0991SDimitry Andric const CallLowering *RISCVSubtarget::getCallLowering() const { 102*0fca6ea1SDimitry Andric if (!CallLoweringInfo) 103*0fca6ea1SDimitry Andric CallLoweringInfo.reset(new RISCVCallLowering(*getTargetLowering())); 1048bcb0991SDimitry Andric return CallLoweringInfo.get(); 1058bcb0991SDimitry Andric } 1068bcb0991SDimitry Andric 1078bcb0991SDimitry Andric InstructionSelector *RISCVSubtarget::getInstructionSelector() const { 108*0fca6ea1SDimitry Andric if (!InstSelector) { 109*0fca6ea1SDimitry Andric InstSelector.reset(createRISCVInstructionSelector( 110*0fca6ea1SDimitry Andric *static_cast<const RISCVTargetMachine *>(&TLInfo.getTargetMachine()), 111*0fca6ea1SDimitry Andric *this, *getRegBankInfo())); 112*0fca6ea1SDimitry Andric } 1138bcb0991SDimitry Andric return InstSelector.get(); 1148bcb0991SDimitry Andric } 1158bcb0991SDimitry Andric 1168bcb0991SDimitry Andric const LegalizerInfo *RISCVSubtarget::getLegalizerInfo() const { 117*0fca6ea1SDimitry Andric if (!Legalizer) 118*0fca6ea1SDimitry Andric Legalizer.reset(new RISCVLegalizerInfo(*this)); 1198bcb0991SDimitry Andric return Legalizer.get(); 1208bcb0991SDimitry Andric } 1218bcb0991SDimitry Andric 122*0fca6ea1SDimitry Andric const RISCVRegisterBankInfo *RISCVSubtarget::getRegBankInfo() const { 123*0fca6ea1SDimitry Andric if (!RegBankInfo) 124*0fca6ea1SDimitry Andric RegBankInfo.reset(new RISCVRegisterBankInfo(getHwMode())); 1258bcb0991SDimitry Andric return RegBankInfo.get(); 1268bcb0991SDimitry Andric } 127fe6060f1SDimitry Andric 12804eeddc0SDimitry Andric bool RISCVSubtarget::useConstantPoolForLargeInts() const { 12904eeddc0SDimitry Andric return !RISCVDisableUsingConstantPoolForLargeInts; 13004eeddc0SDimitry Andric } 13104eeddc0SDimitry Andric 13204eeddc0SDimitry Andric unsigned RISCVSubtarget::getMaxBuildIntsCost() const { 13304eeddc0SDimitry Andric // Loading integer from constant pool needs two instructions (the reason why 13404eeddc0SDimitry Andric // the minimum cost is 2): an address calculation instruction and a load 13504eeddc0SDimitry Andric // instruction. Usually, address calculation and instructions used for 13604eeddc0SDimitry Andric // building integers (addi, slli, etc.) can be done in one cycle, so here we 13704eeddc0SDimitry Andric // set the default cost to (LoadLatency + 1) if no threshold is provided. 13804eeddc0SDimitry Andric return RISCVMaxBuildIntsCost == 0 13904eeddc0SDimitry Andric ? getSchedModel().LoadLatency + 1 14004eeddc0SDimitry Andric : std::max<unsigned>(2, RISCVMaxBuildIntsCost); 14104eeddc0SDimitry Andric } 14204eeddc0SDimitry Andric 143fe6060f1SDimitry Andric unsigned RISCVSubtarget::getMaxRVVVectorSizeInBits() const { 144349cc55cSDimitry Andric assert(hasVInstructions() && 145349cc55cSDimitry Andric "Tried to get vector length without Zve or V extension support!"); 14604eeddc0SDimitry Andric 14704eeddc0SDimitry Andric // ZvlLen specifies the minimum required vlen. The upper bound provided by 14804eeddc0SDimitry Andric // riscv-v-vector-bits-max should be no less than it. 149bdd1243dSDimitry Andric if (RVVVectorBitsMax != 0 && RVVVectorBitsMax < ZvlLen) 15004eeddc0SDimitry Andric report_fatal_error("riscv-v-vector-bits-max specified is lower " 15104eeddc0SDimitry Andric "than the Zvl*b limitation"); 15204eeddc0SDimitry Andric 153bdd1243dSDimitry Andric return RVVVectorBitsMax; 154fe6060f1SDimitry Andric } 155fe6060f1SDimitry Andric 156fe6060f1SDimitry Andric unsigned RISCVSubtarget::getMinRVVVectorSizeInBits() const { 15781ad6265SDimitry Andric assert(hasVInstructions() && 15881ad6265SDimitry Andric "Tried to get vector length without Zve or V extension support!"); 15981ad6265SDimitry Andric 160bdd1243dSDimitry Andric if (RVVVectorBitsMin == -1U) 16181ad6265SDimitry Andric return ZvlLen; 16281ad6265SDimitry Andric 16304eeddc0SDimitry Andric // ZvlLen specifies the minimum required vlen. The lower bound provided by 16404eeddc0SDimitry Andric // riscv-v-vector-bits-min should be no less than it. 165bdd1243dSDimitry Andric if (RVVVectorBitsMin != 0 && RVVVectorBitsMin < ZvlLen) 16604eeddc0SDimitry Andric report_fatal_error("riscv-v-vector-bits-min specified is lower " 16704eeddc0SDimitry Andric "than the Zvl*b limitation"); 16804eeddc0SDimitry Andric 169bdd1243dSDimitry Andric return RVVVectorBitsMin; 170fe6060f1SDimitry Andric } 171fe6060f1SDimitry Andric 172fe6060f1SDimitry Andric unsigned RISCVSubtarget::getMaxLMULForFixedLengthVectors() const { 173349cc55cSDimitry Andric assert(hasVInstructions() && 174349cc55cSDimitry Andric "Tried to get vector length without Zve or V extension support!"); 17506c3fb27SDimitry Andric assert(RVVVectorLMULMax <= 8 && 17606c3fb27SDimitry Andric llvm::has_single_bit<uint32_t>(RVVVectorLMULMax) && 177fe6060f1SDimitry Andric "V extension requires a LMUL to be at most 8 and a power of 2!"); 17806c3fb27SDimitry Andric return llvm::bit_floor(std::clamp<unsigned>(RVVVectorLMULMax, 1, 8)); 179349cc55cSDimitry Andric } 180349cc55cSDimitry Andric 181fe6060f1SDimitry Andric bool RISCVSubtarget::useRVVForFixedLengthVectors() const { 182349cc55cSDimitry Andric return hasVInstructions() && getMinRVVVectorSizeInBits() != 0; 183fe6060f1SDimitry Andric } 18481ad6265SDimitry Andric 185*0fca6ea1SDimitry Andric bool RISCVSubtarget::enableSubRegLiveness() const { return true; } 18681ad6265SDimitry Andric 18781ad6265SDimitry Andric void RISCVSubtarget::getPostRAMutations( 18881ad6265SDimitry Andric std::vector<std::unique_ptr<ScheduleDAGMutation>> &Mutations) const { 189b3edf446SDimitry Andric Mutations.push_back(createMacroFusionDAGMutation(getMacroFusions())); 19081ad6265SDimitry Andric } 1915f757f3fSDimitry Andric 1925f757f3fSDimitry Andric /// Enable use of alias analysis during code generation (during MI 1935f757f3fSDimitry Andric /// scheduling, DAGCombine, etc.). 1945f757f3fSDimitry Andric bool RISCVSubtarget::useAA() const { return UseAA; } 1955f757f3fSDimitry Andric 1965f757f3fSDimitry Andric unsigned RISCVSubtarget::getMinimumJumpTableEntries() const { 1975f757f3fSDimitry Andric return RISCVMinimumJumpTableEntries.getNumOccurrences() > 0 1985f757f3fSDimitry Andric ? RISCVMinimumJumpTableEntries 1995f757f3fSDimitry Andric : TuneInfo->MinimumJumpTableEntries; 2005f757f3fSDimitry Andric } 201