1 //===-- RISCVSubtarget.cpp - RISC-V Subtarget Information -----------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file implements the RISC-V specific subclass of TargetSubtargetInfo. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "RISCVSubtarget.h" 14 #include "GISel/RISCVCallLowering.h" 15 #include "GISel/RISCVLegalizerInfo.h" 16 #include "RISCV.h" 17 #include "RISCVFrameLowering.h" 18 #include "RISCVSelectionDAGInfo.h" 19 #include "RISCVTargetMachine.h" 20 #include "llvm/CodeGen/MacroFusion.h" 21 #include "llvm/CodeGen/ScheduleDAGMutation.h" 22 #include "llvm/MC/TargetRegistry.h" 23 #include "llvm/Support/ErrorHandling.h" 24 25 using namespace llvm; 26 27 #define DEBUG_TYPE "riscv-subtarget" 28 29 #define GET_SUBTARGETINFO_TARGET_DESC 30 #define GET_SUBTARGETINFO_CTOR 31 #include "RISCVGenSubtargetInfo.inc" 32 33 #define GET_RISCV_MACRO_FUSION_PRED_IMPL 34 #include "RISCVGenMacroFusion.inc" 35 36 namespace llvm::RISCVTuneInfoTable { 37 38 #define GET_RISCVTuneInfoTable_IMPL 39 #include "RISCVGenSearchableTables.inc" 40 } // namespace llvm::RISCVTuneInfoTable 41 42 static cl::opt<unsigned> RVVVectorLMULMax( 43 "riscv-v-fixed-length-vector-lmul-max", 44 cl::desc("The maximum LMUL value to use for fixed length vectors. " 45 "Fractional LMUL values are not supported."), 46 cl::init(8), cl::Hidden); 47 48 static cl::opt<bool> RISCVDisableUsingConstantPoolForLargeInts( 49 "riscv-disable-using-constant-pool-for-large-ints", 50 cl::desc("Disable using constant pool for large integers."), 51 cl::init(false), cl::Hidden); 52 53 static cl::opt<unsigned> RISCVMaxBuildIntsCost( 54 "riscv-max-build-ints-cost", 55 cl::desc("The maximum cost used for building integers."), cl::init(0), 56 cl::Hidden); 57 58 static cl::opt<bool> UseAA("riscv-use-aa", cl::init(true), 59 cl::desc("Enable the use of AA during codegen.")); 60 61 static cl::opt<unsigned> RISCVMinimumJumpTableEntries( 62 "riscv-min-jump-table-entries", cl::Hidden, 63 cl::desc("Set minimum number of entries to use a jump table on RISCV")); 64 65 static cl::opt<bool> 66 UseMIPSLoadStorePairsOpt("mips-riscv-load-store-pairs", 67 cl::desc("RISCV: Optimize for load-store bonding"), 68 cl::init(false), cl::Hidden); 69 70 static cl::opt<bool> 71 UseCCMovInsn("riscv-ccmov", cl::desc("RISCV: Use 'mips.ccmov' instruction"), 72 cl::init(true), cl::Hidden); 73 74 void RISCVSubtarget::anchor() {} 75 76 RISCVSubtarget & 77 RISCVSubtarget::initializeSubtargetDependencies(const Triple &TT, StringRef CPU, 78 StringRef TuneCPU, StringRef FS, 79 StringRef ABIName) { 80 // Determine default and user-specified characteristics 81 bool Is64Bit = TT.isArch64Bit(); 82 if (CPU.empty() || CPU == "generic") 83 CPU = Is64Bit ? "generic-rv64" : "generic-rv32"; 84 85 if (TuneCPU.empty()) 86 TuneCPU = CPU; 87 88 TuneInfo = RISCVTuneInfoTable::getRISCVTuneInfo(TuneCPU); 89 // If there is no TuneInfo for this CPU, we fail back to generic. 90 if (!TuneInfo) 91 TuneInfo = RISCVTuneInfoTable::getRISCVTuneInfo("generic"); 92 assert(TuneInfo && "TuneInfo shouldn't be nullptr!"); 93 94 ParseSubtargetFeatures(CPU, TuneCPU, FS); 95 TargetABI = RISCVABI::computeTargetABI(TT, getFeatureBits(), ABIName); 96 RISCVFeatures::validate(TT, getFeatureBits()); 97 return *this; 98 } 99 100 RISCVSubtarget::RISCVSubtarget(const Triple &TT, StringRef CPU, 101 StringRef TuneCPU, StringRef FS, 102 StringRef ABIName, unsigned RVVVectorBitsMin, 103 unsigned RVVVectorBitsMax, 104 const TargetMachine &TM) 105 : RISCVGenSubtargetInfo(TT, CPU, TuneCPU, FS), 106 RVVVectorBitsMin(RVVVectorBitsMin), RVVVectorBitsMax(RVVVectorBitsMax), 107 FrameLowering( 108 initializeSubtargetDependencies(TT, CPU, TuneCPU, FS, ABIName)), 109 InstrInfo(*this), RegInfo(getHwMode()), TLInfo(TM, *this) { 110 TSInfo = std::make_unique<RISCVSelectionDAGInfo>(); 111 } 112 113 RISCVSubtarget::~RISCVSubtarget() = default; 114 115 const SelectionDAGTargetInfo *RISCVSubtarget::getSelectionDAGInfo() const { 116 return TSInfo.get(); 117 } 118 119 const CallLowering *RISCVSubtarget::getCallLowering() const { 120 if (!CallLoweringInfo) 121 CallLoweringInfo.reset(new RISCVCallLowering(*getTargetLowering())); 122 return CallLoweringInfo.get(); 123 } 124 125 InstructionSelector *RISCVSubtarget::getInstructionSelector() const { 126 if (!InstSelector) { 127 InstSelector.reset(createRISCVInstructionSelector( 128 *static_cast<const RISCVTargetMachine *>(&TLInfo.getTargetMachine()), 129 *this, *getRegBankInfo())); 130 } 131 return InstSelector.get(); 132 } 133 134 const LegalizerInfo *RISCVSubtarget::getLegalizerInfo() const { 135 if (!Legalizer) 136 Legalizer.reset(new RISCVLegalizerInfo(*this)); 137 return Legalizer.get(); 138 } 139 140 const RISCVRegisterBankInfo *RISCVSubtarget::getRegBankInfo() const { 141 if (!RegBankInfo) 142 RegBankInfo.reset(new RISCVRegisterBankInfo(getHwMode())); 143 return RegBankInfo.get(); 144 } 145 146 bool RISCVSubtarget::useConstantPoolForLargeInts() const { 147 return !RISCVDisableUsingConstantPoolForLargeInts; 148 } 149 150 unsigned RISCVSubtarget::getMaxBuildIntsCost() const { 151 // Loading integer from constant pool needs two instructions (the reason why 152 // the minimum cost is 2): an address calculation instruction and a load 153 // instruction. Usually, address calculation and instructions used for 154 // building integers (addi, slli, etc.) can be done in one cycle, so here we 155 // set the default cost to (LoadLatency + 1) if no threshold is provided. 156 return RISCVMaxBuildIntsCost == 0 157 ? getSchedModel().LoadLatency + 1 158 : std::max<unsigned>(2, RISCVMaxBuildIntsCost); 159 } 160 161 unsigned RISCVSubtarget::getMaxRVVVectorSizeInBits() const { 162 assert(hasVInstructions() && 163 "Tried to get vector length without Zve or V extension support!"); 164 165 // ZvlLen specifies the minimum required vlen. The upper bound provided by 166 // riscv-v-vector-bits-max should be no less than it. 167 if (RVVVectorBitsMax != 0 && RVVVectorBitsMax < ZvlLen) 168 report_fatal_error("riscv-v-vector-bits-max specified is lower " 169 "than the Zvl*b limitation"); 170 171 return RVVVectorBitsMax; 172 } 173 174 unsigned RISCVSubtarget::getMinRVVVectorSizeInBits() const { 175 assert(hasVInstructions() && 176 "Tried to get vector length without Zve or V extension support!"); 177 178 if (RVVVectorBitsMin == -1U) 179 return ZvlLen; 180 181 // ZvlLen specifies the minimum required vlen. The lower bound provided by 182 // riscv-v-vector-bits-min should be no less than it. 183 if (RVVVectorBitsMin != 0 && RVVVectorBitsMin < ZvlLen) 184 report_fatal_error("riscv-v-vector-bits-min specified is lower " 185 "than the Zvl*b limitation"); 186 187 return RVVVectorBitsMin; 188 } 189 190 unsigned RISCVSubtarget::getMaxLMULForFixedLengthVectors() const { 191 assert(hasVInstructions() && 192 "Tried to get vector length without Zve or V extension support!"); 193 assert(RVVVectorLMULMax <= 8 && 194 llvm::has_single_bit<uint32_t>(RVVVectorLMULMax) && 195 "V extension requires a LMUL to be at most 8 and a power of 2!"); 196 return llvm::bit_floor(std::clamp<unsigned>(RVVVectorLMULMax, 1, 8)); 197 } 198 199 bool RISCVSubtarget::useRVVForFixedLengthVectors() const { 200 return hasVInstructions() && 201 getMinRVVVectorSizeInBits() >= RISCV::RVVBitsPerBlock; 202 } 203 204 bool RISCVSubtarget::enableSubRegLiveness() const { return true; } 205 206 bool RISCVSubtarget::enableMachinePipeliner() const { 207 return getSchedModel().hasInstrSchedModel(); 208 } 209 210 /// Enable use of alias analysis during code generation (during MI 211 /// scheduling, DAGCombine, etc.). 212 bool RISCVSubtarget::useAA() const { return UseAA; } 213 214 unsigned RISCVSubtarget::getMinimumJumpTableEntries() const { 215 return RISCVMinimumJumpTableEntries.getNumOccurrences() > 0 216 ? RISCVMinimumJumpTableEntries 217 : TuneInfo->MinimumJumpTableEntries; 218 } 219 220 void RISCVSubtarget::overrideSchedPolicy(MachineSchedPolicy &Policy, 221 unsigned NumRegionInstrs) const { 222 // Do bidirectional scheduling since it provides a more balanced scheduling 223 // leading to better performance. This will increase compile time. 224 Policy.OnlyTopDown = false; 225 Policy.OnlyBottomUp = false; 226 227 // Disabling the latency heuristic can reduce the number of spills/reloads but 228 // will cause some regressions on some cores. 229 Policy.DisableLatencyHeuristic = DisableLatencySchedHeuristic; 230 231 // Spilling is generally expensive on all RISC-V cores, so always enable 232 // register-pressure tracking. This will increase compile time. 233 Policy.ShouldTrackPressure = true; 234 } 235 236 void RISCVSubtarget::overridePostRASchedPolicy(MachineSchedPolicy &Policy, 237 unsigned NumRegionInstrs) const { 238 MISched::Direction PostRASchedDirection = getPostRASchedDirection(); 239 if (PostRASchedDirection == MISched::TopDown) { 240 Policy.OnlyTopDown = true; 241 Policy.OnlyBottomUp = false; 242 } else if (PostRASchedDirection == MISched::BottomUp) { 243 Policy.OnlyTopDown = false; 244 Policy.OnlyBottomUp = true; 245 } else if (PostRASchedDirection == MISched::Bidirectional) { 246 Policy.OnlyTopDown = false; 247 Policy.OnlyBottomUp = false; 248 } 249 } 250 251 bool RISCVSubtarget::useCCMovInsn() const { 252 return UseCCMovInsn && HasVendorXMIPSCMove; 253 } 254