xref: /llvm-project/clang/lib/Basic/Targets/RISCV.cpp (revision 33c44074714d1d2f3d5f65c3fb842cddb6b689ac)
1 //===--- RISCV.cpp - Implement RISC-V target feature support --------------===//
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 RISC-V TargetInfo objects.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "RISCV.h"
14 #include "clang/Basic/Diagnostic.h"
15 #include "clang/Basic/MacroBuilder.h"
16 #include "clang/Basic/TargetBuiltins.h"
17 #include "llvm/ADT/StringSwitch.h"
18 #include "llvm/Support/raw_ostream.h"
19 #include "llvm/TargetParser/RISCVTargetParser.h"
20 #include <optional>
21 
22 using namespace clang;
23 using namespace clang::targets;
24 
25 ArrayRef<const char *> RISCVTargetInfo::getGCCRegNames() const {
26   // clang-format off
27   static const char *const GCCRegNames[] = {
28       // Integer registers
29       "x0",  "x1",  "x2",  "x3",  "x4",  "x5",  "x6",  "x7",
30       "x8",  "x9",  "x10", "x11", "x12", "x13", "x14", "x15",
31       "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
32       "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31",
33 
34       // Floating point registers
35       "f0",  "f1",  "f2",  "f3",  "f4",  "f5",  "f6",  "f7",
36       "f8",  "f9",  "f10", "f11", "f12", "f13", "f14", "f15",
37       "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
38       "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
39 
40       // Vector registers
41       "v0",  "v1",  "v2",  "v3",  "v4",  "v5",  "v6",  "v7",
42       "v8",  "v9",  "v10", "v11", "v12", "v13", "v14", "v15",
43       "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
44       "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",
45 
46       // CSRs
47       "fflags", "frm", "vtype", "vl", "vxsat", "vxrm", "sf.vcix_state"
48     };
49   // clang-format on
50   return llvm::ArrayRef(GCCRegNames);
51 }
52 
53 ArrayRef<TargetInfo::GCCRegAlias> RISCVTargetInfo::getGCCRegAliases() const {
54   static const TargetInfo::GCCRegAlias GCCRegAliases[] = {
55       {{"zero"}, "x0"}, {{"ra"}, "x1"},   {{"sp"}, "x2"},    {{"gp"}, "x3"},
56       {{"tp"}, "x4"},   {{"t0"}, "x5"},   {{"t1"}, "x6"},    {{"t2"}, "x7"},
57       {{"s0"}, "x8"},   {{"s1"}, "x9"},   {{"a0"}, "x10"},   {{"a1"}, "x11"},
58       {{"a2"}, "x12"},  {{"a3"}, "x13"},  {{"a4"}, "x14"},   {{"a5"}, "x15"},
59       {{"a6"}, "x16"},  {{"a7"}, "x17"},  {{"s2"}, "x18"},   {{"s3"}, "x19"},
60       {{"s4"}, "x20"},  {{"s5"}, "x21"},  {{"s6"}, "x22"},   {{"s7"}, "x23"},
61       {{"s8"}, "x24"},  {{"s9"}, "x25"},  {{"s10"}, "x26"},  {{"s11"}, "x27"},
62       {{"t3"}, "x28"},  {{"t4"}, "x29"},  {{"t5"}, "x30"},   {{"t6"}, "x31"},
63       {{"ft0"}, "f0"},  {{"ft1"}, "f1"},  {{"ft2"}, "f2"},   {{"ft3"}, "f3"},
64       {{"ft4"}, "f4"},  {{"ft5"}, "f5"},  {{"ft6"}, "f6"},   {{"ft7"}, "f7"},
65       {{"fs0"}, "f8"},  {{"fs1"}, "f9"},  {{"fa0"}, "f10"},  {{"fa1"}, "f11"},
66       {{"fa2"}, "f12"}, {{"fa3"}, "f13"}, {{"fa4"}, "f14"},  {{"fa5"}, "f15"},
67       {{"fa6"}, "f16"}, {{"fa7"}, "f17"}, {{"fs2"}, "f18"},  {{"fs3"}, "f19"},
68       {{"fs4"}, "f20"}, {{"fs5"}, "f21"}, {{"fs6"}, "f22"},  {{"fs7"}, "f23"},
69       {{"fs8"}, "f24"}, {{"fs9"}, "f25"}, {{"fs10"}, "f26"}, {{"fs11"}, "f27"},
70       {{"ft8"}, "f28"}, {{"ft9"}, "f29"}, {{"ft10"}, "f30"}, {{"ft11"}, "f31"}};
71   return llvm::ArrayRef(GCCRegAliases);
72 }
73 
74 bool RISCVTargetInfo::validateAsmConstraint(
75     const char *&Name, TargetInfo::ConstraintInfo &Info) const {
76   switch (*Name) {
77   default:
78     return false;
79   case 'I':
80     // A 12-bit signed immediate.
81     Info.setRequiresImmediate(-2048, 2047);
82     return true;
83   case 'J':
84     // Integer zero.
85     Info.setRequiresImmediate(0);
86     return true;
87   case 'K':
88     // A 5-bit unsigned immediate for CSR access instructions.
89     Info.setRequiresImmediate(0, 31);
90     return true;
91   case 'f':
92     // A floating-point register.
93     Info.setAllowsRegister();
94     return true;
95   case 'A':
96     // An address that is held in a general-purpose register.
97     Info.setAllowsMemory();
98     return true;
99   case 's':
100   case 'S': // A symbol or label reference with a constant offset
101     Info.setAllowsRegister();
102     return true;
103   case 'c':
104     // A RVC register - GPR or FPR
105     if (Name[1] == 'r' || Name[1] == 'R' || Name[1] == 'f') {
106       Info.setAllowsRegister();
107       Name += 1;
108       return true;
109     }
110     return false;
111   case 'R':
112     // An even-odd GPR pair
113     Info.setAllowsRegister();
114     return true;
115   case 'v':
116     // A vector register.
117     if (Name[1] == 'r' || Name[1] == 'd' || Name[1] == 'm') {
118       Info.setAllowsRegister();
119       Name += 1;
120       return true;
121     }
122     return false;
123   }
124 }
125 
126 std::string RISCVTargetInfo::convertConstraint(const char *&Constraint) const {
127   std::string R;
128   switch (*Constraint) {
129   // c* and v* are two-letter constraints on RISC-V.
130   case 'c':
131   case 'v':
132     R = std::string("^") + std::string(Constraint, 2);
133     Constraint += 1;
134     break;
135   default:
136     R = TargetInfo::convertConstraint(Constraint);
137     break;
138   }
139   return R;
140 }
141 
142 static unsigned getVersionValue(unsigned MajorVersion, unsigned MinorVersion) {
143   return MajorVersion * 1000000 + MinorVersion * 1000;
144 }
145 
146 void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts,
147                                        MacroBuilder &Builder) const {
148   Builder.defineMacro("__riscv");
149   bool Is64Bit = getTriple().isRISCV64();
150   Builder.defineMacro("__riscv_xlen", Is64Bit ? "64" : "32");
151   StringRef CodeModel = getTargetOpts().CodeModel;
152   unsigned FLen = ISAInfo->getFLen();
153   unsigned MinVLen = ISAInfo->getMinVLen();
154   unsigned MaxELen = ISAInfo->getMaxELen();
155   unsigned MaxELenFp = ISAInfo->getMaxELenFp();
156   if (CodeModel == "default")
157     CodeModel = "small";
158 
159   if (CodeModel == "small")
160     Builder.defineMacro("__riscv_cmodel_medlow");
161   else if (CodeModel == "medium")
162     Builder.defineMacro("__riscv_cmodel_medany");
163   else if (CodeModel == "large")
164     Builder.defineMacro("__riscv_cmodel_large");
165 
166   StringRef ABIName = getABI();
167   if (ABIName == "ilp32f" || ABIName == "lp64f")
168     Builder.defineMacro("__riscv_float_abi_single");
169   else if (ABIName == "ilp32d" || ABIName == "lp64d")
170     Builder.defineMacro("__riscv_float_abi_double");
171   else
172     Builder.defineMacro("__riscv_float_abi_soft");
173 
174   if (ABIName == "ilp32e" || ABIName == "lp64e")
175     Builder.defineMacro("__riscv_abi_rve");
176 
177   Builder.defineMacro("__riscv_arch_test");
178 
179   for (auto &Extension : ISAInfo->getExtensions()) {
180     auto ExtName = Extension.first;
181     auto ExtInfo = Extension.second;
182 
183     Builder.defineMacro(Twine("__riscv_", ExtName),
184                         Twine(getVersionValue(ExtInfo.Major, ExtInfo.Minor)));
185   }
186 
187   if (ISAInfo->hasExtension("zmmul"))
188     Builder.defineMacro("__riscv_mul");
189 
190   if (ISAInfo->hasExtension("m")) {
191     Builder.defineMacro("__riscv_div");
192     Builder.defineMacro("__riscv_muldiv");
193   }
194 
195   if (ISAInfo->hasExtension("a")) {
196     Builder.defineMacro("__riscv_atomic");
197     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
198     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
199     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
200     if (Is64Bit)
201       Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
202   }
203 
204   if (FLen) {
205     Builder.defineMacro("__riscv_flen", Twine(FLen));
206     Builder.defineMacro("__riscv_fdiv");
207     Builder.defineMacro("__riscv_fsqrt");
208   }
209 
210   if (MinVLen) {
211     Builder.defineMacro("__riscv_v_min_vlen", Twine(MinVLen));
212     Builder.defineMacro("__riscv_v_elen", Twine(MaxELen));
213     Builder.defineMacro("__riscv_v_elen_fp", Twine(MaxELenFp));
214   }
215 
216   if (ISAInfo->hasExtension("c"))
217     Builder.defineMacro("__riscv_compressed");
218 
219   if (ISAInfo->hasExtension("zve32x"))
220     Builder.defineMacro("__riscv_vector");
221 
222   // Currently we support the v1.0 RISC-V V intrinsics.
223   Builder.defineMacro("__riscv_v_intrinsic", Twine(getVersionValue(1, 0)));
224 
225   auto VScale = getVScaleRange(Opts);
226   if (VScale && VScale->first && VScale->first == VScale->second)
227     Builder.defineMacro("__riscv_v_fixed_vlen",
228                         Twine(VScale->first * llvm::RISCV::RVVBitsPerBlock));
229 
230   if (FastScalarUnalignedAccess)
231     Builder.defineMacro("__riscv_misaligned_fast");
232   else
233     Builder.defineMacro("__riscv_misaligned_avoid");
234 
235   if (ISAInfo->hasExtension("e")) {
236     if (Is64Bit)
237       Builder.defineMacro("__riscv_64e");
238     else
239       Builder.defineMacro("__riscv_32e");
240   }
241 }
242 
243 static constexpr Builtin::Info BuiltinInfo[] = {
244 #define BUILTIN(ID, TYPE, ATTRS)                                               \
245   {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
246 #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE)                               \
247   {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
248 #include "clang/Basic/BuiltinsRISCVVector.def"
249 #define BUILTIN(ID, TYPE, ATTRS)                                               \
250   {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
251 #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE)                               \
252   {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
253 #include "clang/Basic/BuiltinsRISCV.inc"
254 };
255 
256 ArrayRef<Builtin::Info> RISCVTargetInfo::getTargetBuiltins() const {
257   return llvm::ArrayRef(BuiltinInfo,
258                         clang::RISCV::LastTSBuiltin - Builtin::FirstTSBuiltin);
259 }
260 
261 bool RISCVTargetInfo::initFeatureMap(
262     llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
263     const std::vector<std::string> &FeaturesVec) const {
264 
265   unsigned XLen = 32;
266 
267   if (getTriple().isRISCV64()) {
268     Features["64bit"] = true;
269     XLen = 64;
270   } else {
271     Features["32bit"] = true;
272   }
273 
274   std::vector<std::string> AllFeatures = FeaturesVec;
275   auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, FeaturesVec);
276   if (!ParseResult) {
277     std::string Buffer;
278     llvm::raw_string_ostream OutputErrMsg(Buffer);
279     handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
280       OutputErrMsg << ErrMsg.getMessage();
281     });
282     Diags.Report(diag::err_invalid_feature_combination) << OutputErrMsg.str();
283     return false;
284   }
285 
286   // Append all features, not just new ones, so we override any negatives.
287   llvm::append_range(AllFeatures, (*ParseResult)->toFeatures());
288   return TargetInfo::initFeatureMap(Features, Diags, CPU, AllFeatures);
289 }
290 
291 std::optional<std::pair<unsigned, unsigned>>
292 RISCVTargetInfo::getVScaleRange(const LangOptions &LangOpts) const {
293   // RISCV::RVVBitsPerBlock is 64.
294   unsigned VScaleMin = ISAInfo->getMinVLen() / llvm::RISCV::RVVBitsPerBlock;
295 
296   if (LangOpts.VScaleMin || LangOpts.VScaleMax) {
297     // Treat Zvl*b as a lower bound on vscale.
298     VScaleMin = std::max(VScaleMin, LangOpts.VScaleMin);
299     unsigned VScaleMax = LangOpts.VScaleMax;
300     if (VScaleMax != 0 && VScaleMax < VScaleMin)
301       VScaleMax = VScaleMin;
302     return std::pair<unsigned, unsigned>(VScaleMin ? VScaleMin : 1, VScaleMax);
303   }
304 
305   if (VScaleMin > 0) {
306     unsigned VScaleMax = ISAInfo->getMaxVLen() / llvm::RISCV::RVVBitsPerBlock;
307     return std::make_pair(VScaleMin, VScaleMax);
308   }
309 
310   return std::nullopt;
311 }
312 
313 /// Return true if has this feature, need to sync with handleTargetFeatures.
314 bool RISCVTargetInfo::hasFeature(StringRef Feature) const {
315   bool Is64Bit = getTriple().isRISCV64();
316   auto Result = llvm::StringSwitch<std::optional<bool>>(Feature)
317                     .Case("riscv", true)
318                     .Case("riscv32", !Is64Bit)
319                     .Case("riscv64", Is64Bit)
320                     .Case("32bit", !Is64Bit)
321                     .Case("64bit", Is64Bit)
322                     .Case("experimental", HasExperimental)
323                     .Default(std::nullopt);
324   if (Result)
325     return *Result;
326 
327   return ISAInfo->hasExtension(Feature);
328 }
329 
330 /// Perform initialization based on the user configured set of features.
331 bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
332                                            DiagnosticsEngine &Diags) {
333   unsigned XLen = getTriple().isArch64Bit() ? 64 : 32;
334   auto ParseResult = llvm::RISCVISAInfo::parseFeatures(XLen, Features);
335   if (!ParseResult) {
336     std::string Buffer;
337     llvm::raw_string_ostream OutputErrMsg(Buffer);
338     handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
339       OutputErrMsg << ErrMsg.getMessage();
340     });
341     Diags.Report(diag::err_invalid_feature_combination) << OutputErrMsg.str();
342     return false;
343   } else {
344     ISAInfo = std::move(*ParseResult);
345   }
346 
347   if (ABI.empty())
348     ABI = ISAInfo->computeDefaultABI().str();
349 
350   if (ISAInfo->hasExtension("zfh") || ISAInfo->hasExtension("zhinx"))
351     HasLegalHalfType = true;
352 
353   FastScalarUnalignedAccess =
354       llvm::is_contained(Features, "+unaligned-scalar-mem");
355 
356   if (llvm::is_contained(Features, "+experimental"))
357     HasExperimental = true;
358 
359   if (ABI == "ilp32e" && ISAInfo->hasExtension("d")) {
360     Diags.Report(diag::err_invalid_feature_combination)
361         << "ILP32E cannot be used with the D ISA extension";
362     return false;
363   }
364   return true;
365 }
366 
367 bool RISCVTargetInfo::isValidCPUName(StringRef Name) const {
368   bool Is64Bit = getTriple().isArch64Bit();
369   return llvm::RISCV::parseCPU(Name, Is64Bit);
370 }
371 
372 void RISCVTargetInfo::fillValidCPUList(
373     SmallVectorImpl<StringRef> &Values) const {
374   bool Is64Bit = getTriple().isArch64Bit();
375   llvm::RISCV::fillValidCPUArchList(Values, Is64Bit);
376 }
377 
378 bool RISCVTargetInfo::isValidTuneCPUName(StringRef Name) const {
379   bool Is64Bit = getTriple().isArch64Bit();
380   return llvm::RISCV::parseTuneCPU(Name, Is64Bit);
381 }
382 
383 void RISCVTargetInfo::fillValidTuneCPUList(
384     SmallVectorImpl<StringRef> &Values) const {
385   bool Is64Bit = getTriple().isArch64Bit();
386   llvm::RISCV::fillValidTuneCPUArchList(Values, Is64Bit);
387 }
388 
389 static void populateNegativeRISCVFeatures(std::vector<std::string> &Features) {
390   auto RII = llvm::RISCVISAInfo::parseArchString(
391       "rv64i", /* EnableExperimentalExtension */ true);
392 
393   if (llvm::errorToBool(RII.takeError()))
394     llvm_unreachable("unsupport rv64i");
395 
396   std::vector<std::string> FeatStrings =
397       (*RII)->toFeatures(/* AddAllExtensions */ true);
398   Features.insert(Features.end(), FeatStrings.begin(), FeatStrings.end());
399 }
400 
401 static void handleFullArchString(StringRef FullArchStr,
402                                  std::vector<std::string> &Features) {
403   auto RII = llvm::RISCVISAInfo::parseArchString(
404       FullArchStr, /* EnableExperimentalExtension */ true);
405   if (llvm::errorToBool(RII.takeError())) {
406     // Forward the invalid FullArchStr.
407     Features.push_back(FullArchStr.str());
408   } else {
409     // Append a full list of features, including any negative extensions so that
410     // we override the CPU's features.
411     populateNegativeRISCVFeatures(Features);
412     std::vector<std::string> FeatStrings =
413         (*RII)->toFeatures(/* AddAllExtensions */ true);
414     Features.insert(Features.end(), FeatStrings.begin(), FeatStrings.end());
415   }
416 }
417 
418 ParsedTargetAttr RISCVTargetInfo::parseTargetAttr(StringRef Features) const {
419   ParsedTargetAttr Ret;
420   if (Features == "default")
421     return Ret;
422   SmallVector<StringRef, 1> AttrFeatures;
423   Features.split(AttrFeatures, ";");
424   bool FoundArch = false;
425 
426   auto handleArchExtension = [](StringRef AttrString,
427                                 std::vector<std::string> &Features) {
428     SmallVector<StringRef, 1> Exts;
429     AttrString.split(Exts, ",");
430     for (auto Ext : Exts) {
431       if (Ext.empty())
432         continue;
433 
434       StringRef ExtName = Ext.substr(1);
435       std::string TargetFeature =
436           llvm::RISCVISAInfo::getTargetFeatureForExtension(ExtName);
437       if (!TargetFeature.empty())
438         Features.push_back(Ext.front() + TargetFeature);
439       else
440         Features.push_back(Ext.str());
441     }
442   };
443 
444   for (auto &Feature : AttrFeatures) {
445     Feature = Feature.trim();
446     StringRef AttrString = Feature.split("=").second.trim();
447 
448     if (Feature.starts_with("arch=")) {
449       // Override last features
450       Ret.Features.clear();
451       if (FoundArch)
452         Ret.Duplicate = "arch=";
453       FoundArch = true;
454 
455       if (AttrString.starts_with("+")) {
456         // EXTENSION like arch=+v,+zbb
457         handleArchExtension(AttrString, Ret.Features);
458       } else {
459         // full-arch-string like arch=rv64gcv
460         handleFullArchString(AttrString, Ret.Features);
461       }
462     } else if (Feature.starts_with("cpu=")) {
463       if (!Ret.CPU.empty())
464         Ret.Duplicate = "cpu=";
465 
466       Ret.CPU = AttrString;
467 
468       if (!FoundArch) {
469         // Update Features with CPU's features
470         StringRef MarchFromCPU = llvm::RISCV::getMArchFromMcpu(Ret.CPU);
471         if (MarchFromCPU != "") {
472           Ret.Features.clear();
473           handleFullArchString(MarchFromCPU, Ret.Features);
474         }
475       }
476     } else if (Feature.starts_with("tune=")) {
477       if (!Ret.Tune.empty())
478         Ret.Duplicate = "tune=";
479 
480       Ret.Tune = AttrString;
481     } else if (Feature.starts_with("priority")) {
482       // Skip because it only use for FMV.
483     } else if (Feature.starts_with("+")) {
484       // Handle target_version/target_clones attribute strings
485       // that are already delimited by ','
486       handleArchExtension(Feature, Ret.Features);
487     }
488   }
489   return Ret;
490 }
491 
492 uint64_t RISCVTargetInfo::getFMVPriority(ArrayRef<StringRef> Features) const {
493   // Priority is explicitly specified on RISC-V unlike on other targets, where
494   // it is derived by all the features of a specific version. Therefore if a
495   // feature contains the priority string, then return it immediately.
496   for (StringRef Feature : Features) {
497     auto [LHS, RHS] = Feature.rsplit(';');
498     if (LHS.consume_front("priority="))
499       Feature = LHS;
500     else if (RHS.consume_front("priority="))
501       Feature = RHS;
502     else
503       continue;
504     uint64_t Priority;
505     if (!Feature.getAsInteger(0, Priority))
506       return Priority;
507   }
508   // Default Priority is zero.
509   return 0;
510 }
511 
512 TargetInfo::CallingConvCheckResult
513 RISCVTargetInfo::checkCallingConvention(CallingConv CC) const {
514   switch (CC) {
515   default:
516     return CCCR_Warning;
517   case CC_C:
518   case CC_RISCVVectorCall:
519     return CCCR_OK;
520   }
521 }
522 
523 bool RISCVTargetInfo::validateCpuSupports(StringRef Feature) const {
524   // Only allow extensions we have a known bit position for in the
525   // __riscv_feature_bits structure.
526   return -1 != llvm::RISCVISAInfo::getRISCVFeaturesBitsInfo(Feature).second;
527 }
528 
529 bool RISCVTargetInfo::isValidFeatureName(StringRef Name) const {
530   return llvm::RISCVISAInfo::isSupportedExtensionFeature(Name);
531 }
532 
533 bool RISCVTargetInfo::validateGlobalRegisterVariable(
534     StringRef RegName, unsigned RegSize, bool &HasSizeMismatch) const {
535   if (RegName == "ra" || RegName == "sp" || RegName == "gp" ||
536       RegName == "tp" || RegName.starts_with("x") || RegName.starts_with("a") ||
537       RegName.starts_with("s") || RegName.starts_with("t")) {
538     unsigned XLen = getTriple().isArch64Bit() ? 64 : 32;
539     HasSizeMismatch = RegSize != XLen;
540     return true;
541   }
542   return false;
543 }
544 
545 bool RISCVTargetInfo::validateCpuIs(StringRef CPUName) const {
546   assert(getTriple().isOSLinux() &&
547          "__builtin_cpu_is() is only supported for Linux.");
548 
549   return llvm::RISCV::hasValidCPUModel(CPUName);
550 }
551