1//===---- PPCTargetParser.cpp - Parser for target features ------*- C++ -*-===//
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 a target parser to recognise hardware features
10// for PPC CPUs.
11//
12//===----------------------------------------------------------------------===//
13
14#include "llvm/TargetParser/PPCTargetParser.h"
15#include "llvm/ADT/StringSwitch.h"
16#include "llvm/TargetParser/Host.h"
17
18#define GET_SUBTARGETFEATURES_ENUM
19#define GET_SUBTARGETFEATURES_KV
20#include "llvm/TargetParser/PPCGenTargetFeatures.inc"
21
22namespace llvm {
23namespace PPC {
24
25struct CPUInfo {
26 StringLiteral Name;
27 // FIXME: add the features field for this CPU.
28};
29
30constexpr CPUInfo PPCCPUInfo[] = {
31#define PPC_CPU(Name, Linux_SUPPORT_METHOD, LinuxID, AIX_SUPPORT_METHOD, \
32 AIXID) \
33 {Name},
34#include "llvm/TargetParser/PPCTargetParser.def"
35};
36
37static const CPUInfo *getCPUInfoByName(StringRef CPU) {
38 for (auto &C : PPCCPUInfo)
39 if (C.Name == CPU)
40 return &C;
41 return nullptr;
42}
43
44StringRef normalizeCPUName(StringRef CPUName) {
45 // Clang/LLVM does not actually support code generation
46 // for the 405 CPU. However, there are uses of this CPU ID
47 // in projects that previously used GCC and rely on Clang
48 // accepting it. Clang has always ignored it and passed the
49 // generic CPU ID to the back end.
50 return StringSwitch<StringRef>(CPUName)
51 .Cases(S0: "common", S1: "405", Value: "generic")
52 .Cases(S0: "ppc440", S1: "440fp", Value: "440")
53 .Cases(S0: "630", S1: "power3", Value: "pwr3")
54 .Case(S: "G3", Value: "g3")
55 .Case(S: "G4", Value: "g4")
56 .Case(S: "G4+", Value: "g4+")
57 .Case(S: "8548", Value: "e500")
58 .Case(S: "ppc970", Value: "970")
59 .Case(S: "G5", Value: "g5")
60 .Case(S: "ppca2", Value: "a2")
61 .Case(S: "power4", Value: "pwr4")
62 .Case(S: "power5", Value: "pwr5")
63 .Case(S: "power5x", Value: "pwr5x")
64 .Case(S: "power5+", Value: "pwr5+")
65 .Case(S: "power6", Value: "pwr6")
66 .Case(S: "power6x", Value: "pwr6x")
67 .Case(S: "power7", Value: "pwr7")
68 .Case(S: "power8", Value: "pwr8")
69 .Case(S: "power9", Value: "pwr9")
70 .Case(S: "power10", Value: "pwr10")
71 .Case(S: "power11", Value: "pwr11")
72 .Cases(S0: "powerpc", S1: "powerpc32", Value: "ppc")
73 .Case(S: "powerpc64", Value: "ppc64")
74 .Case(S: "powerpc64le", Value: "ppc64le")
75 .Default(Value: CPUName);
76}
77
78void fillValidCPUList(SmallVectorImpl<StringRef> &Values) {
79 for (const auto &C : PPCCPUInfo)
80 Values.emplace_back(Args: C.Name);
81}
82
83void fillValidTuneCPUList(SmallVectorImpl<StringRef> &Values) {
84 for (const auto &C : PPCCPUInfo)
85 Values.emplace_back(Args: C.Name);
86}
87
88bool isValidCPU(StringRef CPU) {
89 const CPUInfo *Info = getCPUInfoByName(CPU);
90 if (!Info)
91 return false;
92 return true;
93}
94
95StringRef getNormalizedPPCTargetCPU(const Triple &T, StringRef CPUName) {
96 if (!CPUName.empty()) {
97 if (CPUName == "native") {
98 StringRef CPU = sys::getHostCPUName();
99 if (!CPU.empty() && CPU != "generic")
100 return CPU;
101 }
102
103 StringRef CPU = normalizeCPUName(CPUName);
104 if (CPU != "generic" && CPU != "native")
105 return CPU;
106 }
107
108 // LLVM may default to generating code for the native CPU, but, like gcc, we
109 // default to a more generic option for each architecture. (except on AIX)
110 if (T.isOSAIX())
111 return "pwr7";
112 else if (T.getArch() == Triple::ppc64le)
113 return "ppc64le";
114 else if (T.getArch() == Triple::ppc64)
115 return "ppc64";
116
117 return "ppc";
118}
119
120StringRef getNormalizedPPCTuneCPU(const Triple &T, StringRef CPUName) {
121 return getNormalizedPPCTargetCPU(T, CPUName);
122}
123
124std::optional<StringMap<bool>> getPPCDefaultTargetFeatures(const Triple &T,
125 StringRef CPU) {
126 std::optional<StringMap<bool>> FeaturesOpt =
127 getCPUDefaultTargetFeatures(CPU, ProcDesc: BasicPPCSubTypeKV, ProcFeatures: BasicPPCFeatureKV);
128
129 if (!FeaturesOpt.has_value())
130 return std::nullopt;
131
132 StringMap<bool> Features = FeaturesOpt.value();
133 // FIXME: We need to check for the processor model 8548, since the backend
134 // does not support this processor. When this processor model is implemented
135 // within the backend, the following code can be removed.
136 if (CPU == "8548")
137 Features["spe"] = true;
138
139 // The target feature `quadword-atomics` is only supported for 64-bit
140 // POWER8 and above.
141 if (Features.find(Key: "quadword-atomics") != Features.end() && !T.isArch64Bit())
142 Features["quadword-atomics"] = false;
143 return Features;
144}
145} // namespace PPC
146} // namespace llvm
147