1 //===-- RISCVSubtarget.cpp - RISCV 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 RISCV specific subclass of TargetSubtargetInfo. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "RISCVSubtarget.h" 14 #include "RISCV.h" 15 #include "RISCVFrameLowering.h" 16 #include "RISCVMacroFusion.h" 17 #include "RISCVTargetMachine.h" 18 #include "GISel/RISCVCallLowering.h" 19 #include "GISel/RISCVLegalizerInfo.h" 20 #include "GISel/RISCVRegisterBankInfo.h" 21 #include "llvm/MC/TargetRegistry.h" 22 #include "llvm/Support/ErrorHandling.h" 23 24 using namespace llvm; 25 26 #define DEBUG_TYPE "riscv-subtarget" 27 28 #define GET_SUBTARGETINFO_TARGET_DESC 29 #define GET_SUBTARGETINFO_CTOR 30 #include "RISCVGenSubtargetInfo.inc" 31 32 static cl::opt<bool> EnableSubRegLiveness("riscv-enable-subreg-liveness", 33 cl::init(false), cl::Hidden); 34 35 static cl::opt<unsigned> RVVVectorLMULMax( 36 "riscv-v-fixed-length-vector-lmul-max", 37 cl::desc("The maximum LMUL value to use for fixed length vectors. " 38 "Fractional LMUL values are not supported."), 39 cl::init(8), cl::Hidden); 40 41 static cl::opt<bool> RISCVDisableUsingConstantPoolForLargeInts( 42 "riscv-disable-using-constant-pool-for-large-ints", 43 cl::desc("Disable using constant pool for large integers."), 44 cl::init(false), cl::Hidden); 45 46 static cl::opt<unsigned> RISCVMaxBuildIntsCost( 47 "riscv-max-build-ints-cost", 48 cl::desc("The maximum cost used for building integers."), cl::init(0), 49 cl::Hidden); 50 51 void RISCVSubtarget::anchor() {} 52 53 RISCVSubtarget & 54 RISCVSubtarget::initializeSubtargetDependencies(const Triple &TT, StringRef CPU, 55 StringRef TuneCPU, StringRef FS, 56 StringRef ABIName) { 57 // Determine default and user-specified characteristics 58 bool Is64Bit = TT.isArch64Bit(); 59 if (CPU.empty() || CPU == "generic") 60 CPU = Is64Bit ? "generic-rv64" : "generic-rv32"; 61 62 if (TuneCPU.empty()) 63 TuneCPU = CPU; 64 65 ParseSubtargetFeatures(CPU, TuneCPU, FS); 66 if (Is64Bit) { 67 XLenVT = MVT::i64; 68 XLen = 64; 69 } 70 71 TargetABI = RISCVABI::computeTargetABI(TT, getFeatureBits(), ABIName); 72 RISCVFeatures::validate(TT, getFeatureBits()); 73 return *this; 74 } 75 76 RISCVSubtarget::RISCVSubtarget(const Triple &TT, StringRef CPU, 77 StringRef TuneCPU, StringRef FS, 78 StringRef ABIName, unsigned RVVVectorBitsMin, 79 unsigned RVVVectorBitsMax, 80 const TargetMachine &TM) 81 : RISCVGenSubtargetInfo(TT, CPU, TuneCPU, FS), 82 RVVVectorBitsMin(RVVVectorBitsMin), RVVVectorBitsMax(RVVVectorBitsMax), 83 FrameLowering( 84 initializeSubtargetDependencies(TT, CPU, TuneCPU, FS, ABIName)), 85 InstrInfo(*this), RegInfo(getHwMode()), TLInfo(TM, *this) { 86 if (RISCV::isX18ReservedByDefault(TT)) 87 UserReservedRegister.set(RISCV::X18); 88 89 CallLoweringInfo.reset(new RISCVCallLowering(*getTargetLowering())); 90 Legalizer.reset(new RISCVLegalizerInfo(*this)); 91 92 auto *RBI = new RISCVRegisterBankInfo(*getRegisterInfo()); 93 RegBankInfo.reset(RBI); 94 InstSelector.reset(createRISCVInstructionSelector( 95 *static_cast<const RISCVTargetMachine *>(&TM), *this, *RBI)); 96 } 97 98 const CallLowering *RISCVSubtarget::getCallLowering() const { 99 return CallLoweringInfo.get(); 100 } 101 102 InstructionSelector *RISCVSubtarget::getInstructionSelector() const { 103 return InstSelector.get(); 104 } 105 106 const LegalizerInfo *RISCVSubtarget::getLegalizerInfo() const { 107 return Legalizer.get(); 108 } 109 110 const RegisterBankInfo *RISCVSubtarget::getRegBankInfo() const { 111 return RegBankInfo.get(); 112 } 113 114 bool RISCVSubtarget::useConstantPoolForLargeInts() const { 115 return !RISCVDisableUsingConstantPoolForLargeInts; 116 } 117 118 unsigned RISCVSubtarget::getMaxBuildIntsCost() const { 119 // Loading integer from constant pool needs two instructions (the reason why 120 // the minimum cost is 2): an address calculation instruction and a load 121 // instruction. Usually, address calculation and instructions used for 122 // building integers (addi, slli, etc.) can be done in one cycle, so here we 123 // set the default cost to (LoadLatency + 1) if no threshold is provided. 124 return RISCVMaxBuildIntsCost == 0 125 ? getSchedModel().LoadLatency + 1 126 : std::max<unsigned>(2, RISCVMaxBuildIntsCost); 127 } 128 129 unsigned RISCVSubtarget::getMaxRVVVectorSizeInBits() const { 130 assert(hasVInstructions() && 131 "Tried to get vector length without Zve or V extension support!"); 132 133 // ZvlLen specifies the minimum required vlen. The upper bound provided by 134 // riscv-v-vector-bits-max should be no less than it. 135 if (RVVVectorBitsMax != 0 && RVVVectorBitsMax < ZvlLen) 136 report_fatal_error("riscv-v-vector-bits-max specified is lower " 137 "than the Zvl*b limitation"); 138 139 return RVVVectorBitsMax; 140 } 141 142 unsigned RISCVSubtarget::getMinRVVVectorSizeInBits() const { 143 assert(hasVInstructions() && 144 "Tried to get vector length without Zve or V extension support!"); 145 146 if (RVVVectorBitsMin == -1U) 147 return ZvlLen; 148 149 // ZvlLen specifies the minimum required vlen. The lower bound provided by 150 // riscv-v-vector-bits-min should be no less than it. 151 if (RVVVectorBitsMin != 0 && RVVVectorBitsMin < ZvlLen) 152 report_fatal_error("riscv-v-vector-bits-min specified is lower " 153 "than the Zvl*b limitation"); 154 155 return RVVVectorBitsMin; 156 } 157 158 unsigned RISCVSubtarget::getMaxLMULForFixedLengthVectors() const { 159 assert(hasVInstructions() && 160 "Tried to get vector length without Zve or V extension support!"); 161 assert(RVVVectorLMULMax <= 8 && isPowerOf2_32(RVVVectorLMULMax) && 162 "V extension requires a LMUL to be at most 8 and a power of 2!"); 163 return PowerOf2Floor( 164 std::max<unsigned>(std::min<unsigned>(RVVVectorLMULMax, 8), 1)); 165 } 166 167 bool RISCVSubtarget::useRVVForFixedLengthVectors() const { 168 return hasVInstructions() && getMinRVVVectorSizeInBits() != 0; 169 } 170 171 bool RISCVSubtarget::enableSubRegLiveness() const { 172 // FIXME: Enable subregister liveness by default for RVV to better handle 173 // LMUL>1 and segment load/store. 174 return EnableSubRegLiveness; 175 } 176 177 void RISCVSubtarget::getPostRAMutations( 178 std::vector<std::unique_ptr<ScheduleDAGMutation>> &Mutations) const { 179 Mutations.push_back(createRISCVMacroFusionDAGMutation()); 180 } 181