1*03ce13f7SAndroid Build Coastguard Worker //===- subzero/src/IceTargetLowering.cpp - Basic lowering implementation --===//
2*03ce13f7SAndroid Build Coastguard Worker //
3*03ce13f7SAndroid Build Coastguard Worker // The Subzero Code Generator
4*03ce13f7SAndroid Build Coastguard Worker //
5*03ce13f7SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*03ce13f7SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*03ce13f7SAndroid Build Coastguard Worker //
8*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*03ce13f7SAndroid Build Coastguard Worker ///
10*03ce13f7SAndroid Build Coastguard Worker /// \file
11*03ce13f7SAndroid Build Coastguard Worker /// \brief Implements the skeleton of the TargetLowering class.
12*03ce13f7SAndroid Build Coastguard Worker ///
13*03ce13f7SAndroid Build Coastguard Worker /// Specifically this invokes the appropriate lowering method for a given
14*03ce13f7SAndroid Build Coastguard Worker /// instruction kind and driving global register allocation. It also implements
15*03ce13f7SAndroid Build Coastguard Worker /// the non-deleted instruction iteration in LoweringContext.
16*03ce13f7SAndroid Build Coastguard Worker ///
17*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
18*03ce13f7SAndroid Build Coastguard Worker
19*03ce13f7SAndroid Build Coastguard Worker #include "IceTargetLowering.h"
20*03ce13f7SAndroid Build Coastguard Worker
21*03ce13f7SAndroid Build Coastguard Worker #include "IceBitVector.h"
22*03ce13f7SAndroid Build Coastguard Worker #include "IceCfg.h" // setError()
23*03ce13f7SAndroid Build Coastguard Worker #include "IceCfgNode.h"
24*03ce13f7SAndroid Build Coastguard Worker #include "IceGlobalContext.h"
25*03ce13f7SAndroid Build Coastguard Worker #include "IceGlobalInits.h"
26*03ce13f7SAndroid Build Coastguard Worker #include "IceInstVarIter.h"
27*03ce13f7SAndroid Build Coastguard Worker #include "IceLiveness.h"
28*03ce13f7SAndroid Build Coastguard Worker #include "IceOperand.h"
29*03ce13f7SAndroid Build Coastguard Worker #include "IceRegAlloc.h"
30*03ce13f7SAndroid Build Coastguard Worker
31*03ce13f7SAndroid Build Coastguard Worker #include <string>
32*03ce13f7SAndroid Build Coastguard Worker #include <vector>
33*03ce13f7SAndroid Build Coastguard Worker
34*03ce13f7SAndroid Build Coastguard Worker #define TARGET_LOWERING_CLASS_FOR(t) Target_##t
35*03ce13f7SAndroid Build Coastguard Worker
36*03ce13f7SAndroid Build Coastguard Worker // We prevent target-specific implementation details from leaking outside their
37*03ce13f7SAndroid Build Coastguard Worker // implementations by forbidding #include of target-specific header files
38*03ce13f7SAndroid Build Coastguard Worker // anywhere outside their own files. To create target-specific objects
39*03ce13f7SAndroid Build Coastguard Worker // (TargetLowering, TargetDataLowering, and TargetHeaderLowering) we use the
40*03ce13f7SAndroid Build Coastguard Worker // following named constructors. For reference, each target Foo needs to
41*03ce13f7SAndroid Build Coastguard Worker // implement the following named constructors and initializer:
42*03ce13f7SAndroid Build Coastguard Worker //
43*03ce13f7SAndroid Build Coastguard Worker // namespace Foo {
44*03ce13f7SAndroid Build Coastguard Worker // unique_ptr<Ice::TargetLowering> createTargetLowering(Ice::Cfg *);
45*03ce13f7SAndroid Build Coastguard Worker // unique_ptr<Ice::TargetDataLowering>
46*03ce13f7SAndroid Build Coastguard Worker // createTargetDataLowering(Ice::GlobalContext*);
47*03ce13f7SAndroid Build Coastguard Worker // unique_ptr<Ice::TargetHeaderLowering>
48*03ce13f7SAndroid Build Coastguard Worker // createTargetHeaderLowering(Ice::GlobalContext *);
49*03ce13f7SAndroid Build Coastguard Worker // void staticInit(::Ice::GlobalContext *);
50*03ce13f7SAndroid Build Coastguard Worker // }
51*03ce13f7SAndroid Build Coastguard Worker #define SUBZERO_TARGET(X) \
52*03ce13f7SAndroid Build Coastguard Worker namespace X { \
53*03ce13f7SAndroid Build Coastguard Worker std::unique_ptr<::Ice::TargetLowering> \
54*03ce13f7SAndroid Build Coastguard Worker createTargetLowering(::Ice::Cfg *Func); \
55*03ce13f7SAndroid Build Coastguard Worker std::unique_ptr<::Ice::TargetDataLowering> \
56*03ce13f7SAndroid Build Coastguard Worker createTargetDataLowering(::Ice::GlobalContext *Ctx); \
57*03ce13f7SAndroid Build Coastguard Worker std::unique_ptr<::Ice::TargetHeaderLowering> \
58*03ce13f7SAndroid Build Coastguard Worker createTargetHeaderLowering(::Ice::GlobalContext *Ctx); \
59*03ce13f7SAndroid Build Coastguard Worker void staticInit(::Ice::GlobalContext *Ctx); \
60*03ce13f7SAndroid Build Coastguard Worker bool shouldBePooled(const ::Ice::Constant *C); \
61*03ce13f7SAndroid Build Coastguard Worker ::Ice::Type getPointerType(); \
62*03ce13f7SAndroid Build Coastguard Worker } // end of namespace X
63*03ce13f7SAndroid Build Coastguard Worker #include "SZTargets.def"
64*03ce13f7SAndroid Build Coastguard Worker #undef SUBZERO_TARGET
65*03ce13f7SAndroid Build Coastguard Worker
66*03ce13f7SAndroid Build Coastguard Worker namespace Ice {
init(CfgNode * N)67*03ce13f7SAndroid Build Coastguard Worker void LoweringContext::init(CfgNode *N) {
68*03ce13f7SAndroid Build Coastguard Worker Node = N;
69*03ce13f7SAndroid Build Coastguard Worker End = getNode()->getInsts().end();
70*03ce13f7SAndroid Build Coastguard Worker rewind();
71*03ce13f7SAndroid Build Coastguard Worker advanceForward(Next);
72*03ce13f7SAndroid Build Coastguard Worker }
73*03ce13f7SAndroid Build Coastguard Worker
rewind()74*03ce13f7SAndroid Build Coastguard Worker void LoweringContext::rewind() {
75*03ce13f7SAndroid Build Coastguard Worker Begin = getNode()->getInsts().begin();
76*03ce13f7SAndroid Build Coastguard Worker Cur = Begin;
77*03ce13f7SAndroid Build Coastguard Worker skipDeleted(Cur);
78*03ce13f7SAndroid Build Coastguard Worker Next = Cur;
79*03ce13f7SAndroid Build Coastguard Worker availabilityReset();
80*03ce13f7SAndroid Build Coastguard Worker }
81*03ce13f7SAndroid Build Coastguard Worker
insert(Inst * Instr)82*03ce13f7SAndroid Build Coastguard Worker void LoweringContext::insert(Inst *Instr) {
83*03ce13f7SAndroid Build Coastguard Worker getNode()->getInsts().insert(Next, Instr);
84*03ce13f7SAndroid Build Coastguard Worker LastInserted = Instr;
85*03ce13f7SAndroid Build Coastguard Worker }
86*03ce13f7SAndroid Build Coastguard Worker
skipDeleted(InstList::iterator & I) const87*03ce13f7SAndroid Build Coastguard Worker void LoweringContext::skipDeleted(InstList::iterator &I) const {
88*03ce13f7SAndroid Build Coastguard Worker while (I != End && I->isDeleted())
89*03ce13f7SAndroid Build Coastguard Worker ++I;
90*03ce13f7SAndroid Build Coastguard Worker }
91*03ce13f7SAndroid Build Coastguard Worker
advanceForward(InstList::iterator & I) const92*03ce13f7SAndroid Build Coastguard Worker void LoweringContext::advanceForward(InstList::iterator &I) const {
93*03ce13f7SAndroid Build Coastguard Worker if (I != End) {
94*03ce13f7SAndroid Build Coastguard Worker ++I;
95*03ce13f7SAndroid Build Coastguard Worker skipDeleted(I);
96*03ce13f7SAndroid Build Coastguard Worker }
97*03ce13f7SAndroid Build Coastguard Worker }
98*03ce13f7SAndroid Build Coastguard Worker
getLastInserted() const99*03ce13f7SAndroid Build Coastguard Worker Inst *LoweringContext::getLastInserted() const {
100*03ce13f7SAndroid Build Coastguard Worker assert(LastInserted);
101*03ce13f7SAndroid Build Coastguard Worker return LastInserted;
102*03ce13f7SAndroid Build Coastguard Worker }
103*03ce13f7SAndroid Build Coastguard Worker
availabilityReset()104*03ce13f7SAndroid Build Coastguard Worker void LoweringContext::availabilityReset() {
105*03ce13f7SAndroid Build Coastguard Worker LastDest = nullptr;
106*03ce13f7SAndroid Build Coastguard Worker LastSrc = nullptr;
107*03ce13f7SAndroid Build Coastguard Worker }
108*03ce13f7SAndroid Build Coastguard Worker
availabilityUpdate()109*03ce13f7SAndroid Build Coastguard Worker void LoweringContext::availabilityUpdate() {
110*03ce13f7SAndroid Build Coastguard Worker availabilityReset();
111*03ce13f7SAndroid Build Coastguard Worker Inst *Instr = LastInserted;
112*03ce13f7SAndroid Build Coastguard Worker if (Instr == nullptr)
113*03ce13f7SAndroid Build Coastguard Worker return;
114*03ce13f7SAndroid Build Coastguard Worker if (!Instr->isVarAssign())
115*03ce13f7SAndroid Build Coastguard Worker return;
116*03ce13f7SAndroid Build Coastguard Worker // Since isVarAssign() is true, the source operand must be a Variable.
117*03ce13f7SAndroid Build Coastguard Worker LastDest = Instr->getDest();
118*03ce13f7SAndroid Build Coastguard Worker LastSrc = llvm::cast<Variable>(Instr->getSrc(0));
119*03ce13f7SAndroid Build Coastguard Worker }
120*03ce13f7SAndroid Build Coastguard Worker
availabilityGet(Operand * Src) const121*03ce13f7SAndroid Build Coastguard Worker Variable *LoweringContext::availabilityGet(Operand *Src) const {
122*03ce13f7SAndroid Build Coastguard Worker assert(Src);
123*03ce13f7SAndroid Build Coastguard Worker if (Src == LastDest)
124*03ce13f7SAndroid Build Coastguard Worker return LastSrc;
125*03ce13f7SAndroid Build Coastguard Worker return nullptr;
126*03ce13f7SAndroid Build Coastguard Worker }
127*03ce13f7SAndroid Build Coastguard Worker
128*03ce13f7SAndroid Build Coastguard Worker namespace {
129*03ce13f7SAndroid Build Coastguard Worker
printRegisterSet(Ostream & Str,const SmallBitVector & Bitset,std::function<std::string (RegNumT)> getRegName,const std::string & LineIndentString)130*03ce13f7SAndroid Build Coastguard Worker void printRegisterSet(Ostream &Str, const SmallBitVector &Bitset,
131*03ce13f7SAndroid Build Coastguard Worker std::function<std::string(RegNumT)> getRegName,
132*03ce13f7SAndroid Build Coastguard Worker const std::string &LineIndentString) {
133*03ce13f7SAndroid Build Coastguard Worker constexpr size_t RegistersPerLine = 16;
134*03ce13f7SAndroid Build Coastguard Worker size_t Count = 0;
135*03ce13f7SAndroid Build Coastguard Worker for (RegNumT RegNum : RegNumBVIter(Bitset)) {
136*03ce13f7SAndroid Build Coastguard Worker if (Count == 0) {
137*03ce13f7SAndroid Build Coastguard Worker Str << LineIndentString;
138*03ce13f7SAndroid Build Coastguard Worker } else {
139*03ce13f7SAndroid Build Coastguard Worker Str << ",";
140*03ce13f7SAndroid Build Coastguard Worker }
141*03ce13f7SAndroid Build Coastguard Worker if (Count > 0 && Count % RegistersPerLine == 0)
142*03ce13f7SAndroid Build Coastguard Worker Str << "\n" << LineIndentString;
143*03ce13f7SAndroid Build Coastguard Worker ++Count;
144*03ce13f7SAndroid Build Coastguard Worker Str << getRegName(RegNum);
145*03ce13f7SAndroid Build Coastguard Worker }
146*03ce13f7SAndroid Build Coastguard Worker if (Count)
147*03ce13f7SAndroid Build Coastguard Worker Str << "\n";
148*03ce13f7SAndroid Build Coastguard Worker }
149*03ce13f7SAndroid Build Coastguard Worker
150*03ce13f7SAndroid Build Coastguard Worker // Splits "<class>:<reg>" into "<class>" plus "<reg>". If there is no <class>
151*03ce13f7SAndroid Build Coastguard Worker // component, the result is "" plus "<reg>".
splitToClassAndName(const std::string & RegName,std::string * SplitRegClass,std::string * SplitRegName)152*03ce13f7SAndroid Build Coastguard Worker void splitToClassAndName(const std::string &RegName, std::string *SplitRegClass,
153*03ce13f7SAndroid Build Coastguard Worker std::string *SplitRegName) {
154*03ce13f7SAndroid Build Coastguard Worker constexpr const char Separator[] = ":";
155*03ce13f7SAndroid Build Coastguard Worker constexpr size_t SeparatorWidth = llvm::array_lengthof(Separator) - 1;
156*03ce13f7SAndroid Build Coastguard Worker size_t Pos = RegName.find(Separator);
157*03ce13f7SAndroid Build Coastguard Worker if (Pos == std::string::npos) {
158*03ce13f7SAndroid Build Coastguard Worker *SplitRegClass = "";
159*03ce13f7SAndroid Build Coastguard Worker *SplitRegName = RegName;
160*03ce13f7SAndroid Build Coastguard Worker } else {
161*03ce13f7SAndroid Build Coastguard Worker *SplitRegClass = RegName.substr(0, Pos);
162*03ce13f7SAndroid Build Coastguard Worker *SplitRegName = RegName.substr(Pos + SeparatorWidth);
163*03ce13f7SAndroid Build Coastguard Worker }
164*03ce13f7SAndroid Build Coastguard Worker }
165*03ce13f7SAndroid Build Coastguard Worker
badTargetFatalError(TargetArch Target)166*03ce13f7SAndroid Build Coastguard Worker LLVM_ATTRIBUTE_NORETURN void badTargetFatalError(TargetArch Target) {
167*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error("Unsupported target: " +
168*03ce13f7SAndroid Build Coastguard Worker std::string(targetArchString(Target)));
169*03ce13f7SAndroid Build Coastguard Worker }
170*03ce13f7SAndroid Build Coastguard Worker
171*03ce13f7SAndroid Build Coastguard Worker } // end of anonymous namespace
172*03ce13f7SAndroid Build Coastguard Worker
filterTypeToRegisterSet(GlobalContext * Ctx,int32_t NumRegs,SmallBitVector TypeToRegisterSet[],size_t TypeToRegisterSetSize,std::function<std::string (RegNumT)> getRegName,std::function<const char * (RegClass)> getRegClassName)173*03ce13f7SAndroid Build Coastguard Worker void TargetLowering::filterTypeToRegisterSet(
174*03ce13f7SAndroid Build Coastguard Worker GlobalContext *Ctx, int32_t NumRegs, SmallBitVector TypeToRegisterSet[],
175*03ce13f7SAndroid Build Coastguard Worker size_t TypeToRegisterSetSize,
176*03ce13f7SAndroid Build Coastguard Worker std::function<std::string(RegNumT)> getRegName,
177*03ce13f7SAndroid Build Coastguard Worker std::function<const char *(RegClass)> getRegClassName) {
178*03ce13f7SAndroid Build Coastguard Worker std::vector<SmallBitVector> UseSet(TypeToRegisterSetSize,
179*03ce13f7SAndroid Build Coastguard Worker SmallBitVector(NumRegs));
180*03ce13f7SAndroid Build Coastguard Worker std::vector<SmallBitVector> ExcludeSet(TypeToRegisterSetSize,
181*03ce13f7SAndroid Build Coastguard Worker SmallBitVector(NumRegs));
182*03ce13f7SAndroid Build Coastguard Worker
183*03ce13f7SAndroid Build Coastguard Worker std::unordered_map<std::string, RegNumT> RegNameToIndex;
184*03ce13f7SAndroid Build Coastguard Worker for (int32_t RegIndex = 0; RegIndex < NumRegs; ++RegIndex) {
185*03ce13f7SAndroid Build Coastguard Worker const auto RegNum = RegNumT::fromInt(RegIndex);
186*03ce13f7SAndroid Build Coastguard Worker RegNameToIndex[getRegName(RegNum)] = RegNum;
187*03ce13f7SAndroid Build Coastguard Worker }
188*03ce13f7SAndroid Build Coastguard Worker
189*03ce13f7SAndroid Build Coastguard Worker std::vector<std::string> BadRegNames;
190*03ce13f7SAndroid Build Coastguard Worker
191*03ce13f7SAndroid Build Coastguard Worker // The processRegList function iterates across the RegNames vector. Each
192*03ce13f7SAndroid Build Coastguard Worker // entry in the vector is a string of the form "<reg>" or "<class>:<reg>".
193*03ce13f7SAndroid Build Coastguard Worker // The register class and register number are computed, and the corresponding
194*03ce13f7SAndroid Build Coastguard Worker // bit is set in RegSet[][]. If "<class>:" is missing, then the bit is set
195*03ce13f7SAndroid Build Coastguard Worker // for all classes.
196*03ce13f7SAndroid Build Coastguard Worker auto processRegList = [&](const std::vector<std::string> &RegNames,
197*03ce13f7SAndroid Build Coastguard Worker std::vector<SmallBitVector> &RegSet) {
198*03ce13f7SAndroid Build Coastguard Worker for (const std::string &RegClassAndName : RegNames) {
199*03ce13f7SAndroid Build Coastguard Worker std::string RClass;
200*03ce13f7SAndroid Build Coastguard Worker std::string RName;
201*03ce13f7SAndroid Build Coastguard Worker splitToClassAndName(RegClassAndName, &RClass, &RName);
202*03ce13f7SAndroid Build Coastguard Worker if (!RegNameToIndex.count(RName)) {
203*03ce13f7SAndroid Build Coastguard Worker BadRegNames.push_back(RName);
204*03ce13f7SAndroid Build Coastguard Worker continue;
205*03ce13f7SAndroid Build Coastguard Worker }
206*03ce13f7SAndroid Build Coastguard Worker const int32_t RegIndex = RegNameToIndex.at(RName);
207*03ce13f7SAndroid Build Coastguard Worker for (SizeT TypeIndex = 0; TypeIndex < TypeToRegisterSetSize;
208*03ce13f7SAndroid Build Coastguard Worker ++TypeIndex) {
209*03ce13f7SAndroid Build Coastguard Worker if (RClass.empty() ||
210*03ce13f7SAndroid Build Coastguard Worker RClass == getRegClassName(static_cast<RegClass>(TypeIndex))) {
211*03ce13f7SAndroid Build Coastguard Worker RegSet[TypeIndex][RegIndex] = TypeToRegisterSet[TypeIndex][RegIndex];
212*03ce13f7SAndroid Build Coastguard Worker }
213*03ce13f7SAndroid Build Coastguard Worker }
214*03ce13f7SAndroid Build Coastguard Worker }
215*03ce13f7SAndroid Build Coastguard Worker };
216*03ce13f7SAndroid Build Coastguard Worker
217*03ce13f7SAndroid Build Coastguard Worker processRegList(getFlags().getUseRestrictedRegisters(), UseSet);
218*03ce13f7SAndroid Build Coastguard Worker processRegList(getFlags().getExcludedRegisters(), ExcludeSet);
219*03ce13f7SAndroid Build Coastguard Worker
220*03ce13f7SAndroid Build Coastguard Worker if (!BadRegNames.empty()) {
221*03ce13f7SAndroid Build Coastguard Worker std::string Buffer;
222*03ce13f7SAndroid Build Coastguard Worker llvm::raw_string_ostream StrBuf(Buffer);
223*03ce13f7SAndroid Build Coastguard Worker StrBuf << "Unrecognized use/exclude registers:";
224*03ce13f7SAndroid Build Coastguard Worker for (const auto &RegName : BadRegNames)
225*03ce13f7SAndroid Build Coastguard Worker StrBuf << " " << RegName;
226*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error(StrBuf.str());
227*03ce13f7SAndroid Build Coastguard Worker }
228*03ce13f7SAndroid Build Coastguard Worker
229*03ce13f7SAndroid Build Coastguard Worker // Apply filters.
230*03ce13f7SAndroid Build Coastguard Worker for (size_t TypeIndex = 0; TypeIndex < TypeToRegisterSetSize; ++TypeIndex) {
231*03ce13f7SAndroid Build Coastguard Worker SmallBitVector *TypeBitSet = &TypeToRegisterSet[TypeIndex];
232*03ce13f7SAndroid Build Coastguard Worker SmallBitVector *UseBitSet = &UseSet[TypeIndex];
233*03ce13f7SAndroid Build Coastguard Worker SmallBitVector *ExcludeBitSet = &ExcludeSet[TypeIndex];
234*03ce13f7SAndroid Build Coastguard Worker if (UseBitSet->any())
235*03ce13f7SAndroid Build Coastguard Worker *TypeBitSet = *UseBitSet;
236*03ce13f7SAndroid Build Coastguard Worker (*TypeBitSet).reset(*ExcludeBitSet);
237*03ce13f7SAndroid Build Coastguard Worker }
238*03ce13f7SAndroid Build Coastguard Worker
239*03ce13f7SAndroid Build Coastguard Worker // Display filtered register sets, if requested.
240*03ce13f7SAndroid Build Coastguard Worker if (BuildDefs::dump() && NumRegs &&
241*03ce13f7SAndroid Build Coastguard Worker (getFlags().getVerbose() & IceV_AvailableRegs)) {
242*03ce13f7SAndroid Build Coastguard Worker Ostream &Str = Ctx->getStrDump();
243*03ce13f7SAndroid Build Coastguard Worker const std::string Indent = " ";
244*03ce13f7SAndroid Build Coastguard Worker const std::string IndentTwice = Indent + Indent;
245*03ce13f7SAndroid Build Coastguard Worker Str << "Registers available for register allocation:\n";
246*03ce13f7SAndroid Build Coastguard Worker for (size_t TypeIndex = 0; TypeIndex < TypeToRegisterSetSize; ++TypeIndex) {
247*03ce13f7SAndroid Build Coastguard Worker Str << Indent << getRegClassName(static_cast<RegClass>(TypeIndex))
248*03ce13f7SAndroid Build Coastguard Worker << ":\n";
249*03ce13f7SAndroid Build Coastguard Worker printRegisterSet(Str, TypeToRegisterSet[TypeIndex], getRegName,
250*03ce13f7SAndroid Build Coastguard Worker IndentTwice);
251*03ce13f7SAndroid Build Coastguard Worker }
252*03ce13f7SAndroid Build Coastguard Worker Str << "\n";
253*03ce13f7SAndroid Build Coastguard Worker }
254*03ce13f7SAndroid Build Coastguard Worker }
255*03ce13f7SAndroid Build Coastguard Worker
256*03ce13f7SAndroid Build Coastguard Worker std::unique_ptr<TargetLowering>
createLowering(TargetArch Target,Cfg * Func)257*03ce13f7SAndroid Build Coastguard Worker TargetLowering::createLowering(TargetArch Target, Cfg *Func) {
258*03ce13f7SAndroid Build Coastguard Worker switch (Target) {
259*03ce13f7SAndroid Build Coastguard Worker default:
260*03ce13f7SAndroid Build Coastguard Worker badTargetFatalError(Target);
261*03ce13f7SAndroid Build Coastguard Worker #define SUBZERO_TARGET(X) \
262*03ce13f7SAndroid Build Coastguard Worker case TARGET_LOWERING_CLASS_FOR(X): \
263*03ce13f7SAndroid Build Coastguard Worker return ::X::createTargetLowering(Func);
264*03ce13f7SAndroid Build Coastguard Worker #include "SZTargets.def"
265*03ce13f7SAndroid Build Coastguard Worker #undef SUBZERO_TARGET
266*03ce13f7SAndroid Build Coastguard Worker }
267*03ce13f7SAndroid Build Coastguard Worker }
268*03ce13f7SAndroid Build Coastguard Worker
staticInit(GlobalContext * Ctx)269*03ce13f7SAndroid Build Coastguard Worker void TargetLowering::staticInit(GlobalContext *Ctx) {
270*03ce13f7SAndroid Build Coastguard Worker const TargetArch Target = getFlags().getTargetArch();
271*03ce13f7SAndroid Build Coastguard Worker // Call the specified target's static initializer.
272*03ce13f7SAndroid Build Coastguard Worker switch (Target) {
273*03ce13f7SAndroid Build Coastguard Worker default:
274*03ce13f7SAndroid Build Coastguard Worker badTargetFatalError(Target);
275*03ce13f7SAndroid Build Coastguard Worker #define SUBZERO_TARGET(X) \
276*03ce13f7SAndroid Build Coastguard Worker case TARGET_LOWERING_CLASS_FOR(X): { \
277*03ce13f7SAndroid Build Coastguard Worker static bool InitGuard##X = false; \
278*03ce13f7SAndroid Build Coastguard Worker if (InitGuard##X) { \
279*03ce13f7SAndroid Build Coastguard Worker return; \
280*03ce13f7SAndroid Build Coastguard Worker } \
281*03ce13f7SAndroid Build Coastguard Worker InitGuard##X = true; \
282*03ce13f7SAndroid Build Coastguard Worker ::X::staticInit(Ctx); \
283*03ce13f7SAndroid Build Coastguard Worker } break;
284*03ce13f7SAndroid Build Coastguard Worker #include "SZTargets.def"
285*03ce13f7SAndroid Build Coastguard Worker #undef SUBZERO_TARGET
286*03ce13f7SAndroid Build Coastguard Worker }
287*03ce13f7SAndroid Build Coastguard Worker }
288*03ce13f7SAndroid Build Coastguard Worker
shouldBePooled(const Constant * C)289*03ce13f7SAndroid Build Coastguard Worker bool TargetLowering::shouldBePooled(const Constant *C) {
290*03ce13f7SAndroid Build Coastguard Worker const TargetArch Target = getFlags().getTargetArch();
291*03ce13f7SAndroid Build Coastguard Worker switch (Target) {
292*03ce13f7SAndroid Build Coastguard Worker default:
293*03ce13f7SAndroid Build Coastguard Worker return false;
294*03ce13f7SAndroid Build Coastguard Worker #define SUBZERO_TARGET(X) \
295*03ce13f7SAndroid Build Coastguard Worker case TARGET_LOWERING_CLASS_FOR(X): \
296*03ce13f7SAndroid Build Coastguard Worker return ::X::shouldBePooled(C);
297*03ce13f7SAndroid Build Coastguard Worker #include "SZTargets.def"
298*03ce13f7SAndroid Build Coastguard Worker #undef SUBZERO_TARGET
299*03ce13f7SAndroid Build Coastguard Worker }
300*03ce13f7SAndroid Build Coastguard Worker }
301*03ce13f7SAndroid Build Coastguard Worker
getPointerType()302*03ce13f7SAndroid Build Coastguard Worker ::Ice::Type TargetLowering::getPointerType() {
303*03ce13f7SAndroid Build Coastguard Worker const TargetArch Target = getFlags().getTargetArch();
304*03ce13f7SAndroid Build Coastguard Worker switch (Target) {
305*03ce13f7SAndroid Build Coastguard Worker default:
306*03ce13f7SAndroid Build Coastguard Worker return ::Ice::IceType_void;
307*03ce13f7SAndroid Build Coastguard Worker #define SUBZERO_TARGET(X) \
308*03ce13f7SAndroid Build Coastguard Worker case TARGET_LOWERING_CLASS_FOR(X): \
309*03ce13f7SAndroid Build Coastguard Worker return ::X::getPointerType();
310*03ce13f7SAndroid Build Coastguard Worker #include "SZTargets.def"
311*03ce13f7SAndroid Build Coastguard Worker #undef SUBZERO_TARGET
312*03ce13f7SAndroid Build Coastguard Worker }
313*03ce13f7SAndroid Build Coastguard Worker }
314*03ce13f7SAndroid Build Coastguard Worker
TargetLowering(Cfg * Func)315*03ce13f7SAndroid Build Coastguard Worker TargetLowering::TargetLowering(Cfg *Func)
316*03ce13f7SAndroid Build Coastguard Worker : Func(Func), Ctx(Func->getContext()) {}
317*03ce13f7SAndroid Build Coastguard Worker
genTargetHelperCalls()318*03ce13f7SAndroid Build Coastguard Worker void TargetLowering::genTargetHelperCalls() {
319*03ce13f7SAndroid Build Coastguard Worker TimerMarker T(TimerStack::TT_genHelpers, Func);
320*03ce13f7SAndroid Build Coastguard Worker Utils::BoolFlagSaver _(GeneratingTargetHelpers, true);
321*03ce13f7SAndroid Build Coastguard Worker for (CfgNode *Node : Func->getNodes()) {
322*03ce13f7SAndroid Build Coastguard Worker Context.init(Node);
323*03ce13f7SAndroid Build Coastguard Worker while (!Context.atEnd()) {
324*03ce13f7SAndroid Build Coastguard Worker PostIncrLoweringContext _(Context);
325*03ce13f7SAndroid Build Coastguard Worker genTargetHelperCallFor(iteratorToInst(Context.getCur()));
326*03ce13f7SAndroid Build Coastguard Worker }
327*03ce13f7SAndroid Build Coastguard Worker }
328*03ce13f7SAndroid Build Coastguard Worker }
329*03ce13f7SAndroid Build Coastguard Worker
doAddressOpt()330*03ce13f7SAndroid Build Coastguard Worker void TargetLowering::doAddressOpt() {
331*03ce13f7SAndroid Build Coastguard Worker doAddressOptOther();
332*03ce13f7SAndroid Build Coastguard Worker if (llvm::isa<InstLoad>(*Context.getCur()))
333*03ce13f7SAndroid Build Coastguard Worker doAddressOptLoad();
334*03ce13f7SAndroid Build Coastguard Worker else if (llvm::isa<InstStore>(*Context.getCur()))
335*03ce13f7SAndroid Build Coastguard Worker doAddressOptStore();
336*03ce13f7SAndroid Build Coastguard Worker else if (auto *Intrinsic =
337*03ce13f7SAndroid Build Coastguard Worker llvm::dyn_cast<InstIntrinsic>(&*Context.getCur())) {
338*03ce13f7SAndroid Build Coastguard Worker if (Intrinsic->getIntrinsicID() == Intrinsics::LoadSubVector)
339*03ce13f7SAndroid Build Coastguard Worker doAddressOptLoadSubVector();
340*03ce13f7SAndroid Build Coastguard Worker else if (Intrinsic->getIntrinsicID() == Intrinsics::StoreSubVector)
341*03ce13f7SAndroid Build Coastguard Worker doAddressOptStoreSubVector();
342*03ce13f7SAndroid Build Coastguard Worker }
343*03ce13f7SAndroid Build Coastguard Worker Context.advanceCur();
344*03ce13f7SAndroid Build Coastguard Worker Context.advanceNext();
345*03ce13f7SAndroid Build Coastguard Worker }
346*03ce13f7SAndroid Build Coastguard Worker
347*03ce13f7SAndroid Build Coastguard Worker // Lowers a single instruction according to the information in Context, by
348*03ce13f7SAndroid Build Coastguard Worker // checking the Context.Cur instruction kind and calling the appropriate
349*03ce13f7SAndroid Build Coastguard Worker // lowering method. The lowering method should insert target instructions at
350*03ce13f7SAndroid Build Coastguard Worker // the Cur.Next insertion point, and should not delete the Context.Cur
351*03ce13f7SAndroid Build Coastguard Worker // instruction or advance Context.Cur.
352*03ce13f7SAndroid Build Coastguard Worker //
353*03ce13f7SAndroid Build Coastguard Worker // The lowering method may look ahead in the instruction stream as desired, and
354*03ce13f7SAndroid Build Coastguard Worker // lower additional instructions in conjunction with the current one, for
355*03ce13f7SAndroid Build Coastguard Worker // example fusing a compare and branch. If it does, it should advance
356*03ce13f7SAndroid Build Coastguard Worker // Context.Cur to point to the next non-deleted instruction to process, and it
357*03ce13f7SAndroid Build Coastguard Worker // should delete any additional instructions it consumes.
lower()358*03ce13f7SAndroid Build Coastguard Worker void TargetLowering::lower() {
359*03ce13f7SAndroid Build Coastguard Worker assert(!Context.atEnd());
360*03ce13f7SAndroid Build Coastguard Worker Inst *Instr = iteratorToInst(Context.getCur());
361*03ce13f7SAndroid Build Coastguard Worker Instr->deleteIfDead();
362*03ce13f7SAndroid Build Coastguard Worker if (!Instr->isDeleted() && !llvm::isa<InstFakeDef>(Instr) &&
363*03ce13f7SAndroid Build Coastguard Worker !llvm::isa<InstFakeUse>(Instr)) {
364*03ce13f7SAndroid Build Coastguard Worker // Mark the current instruction as deleted before lowering, otherwise the
365*03ce13f7SAndroid Build Coastguard Worker // Dest variable will likely get marked as non-SSA. See
366*03ce13f7SAndroid Build Coastguard Worker // Variable::setDefinition(). However, just pass-through FakeDef and
367*03ce13f7SAndroid Build Coastguard Worker // FakeUse instructions that might have been inserted prior to lowering.
368*03ce13f7SAndroid Build Coastguard Worker Instr->setDeleted();
369*03ce13f7SAndroid Build Coastguard Worker switch (Instr->getKind()) {
370*03ce13f7SAndroid Build Coastguard Worker case Inst::Alloca:
371*03ce13f7SAndroid Build Coastguard Worker lowerAlloca(llvm::cast<InstAlloca>(Instr));
372*03ce13f7SAndroid Build Coastguard Worker break;
373*03ce13f7SAndroid Build Coastguard Worker case Inst::Arithmetic:
374*03ce13f7SAndroid Build Coastguard Worker lowerArithmetic(llvm::cast<InstArithmetic>(Instr));
375*03ce13f7SAndroid Build Coastguard Worker break;
376*03ce13f7SAndroid Build Coastguard Worker case Inst::Assign:
377*03ce13f7SAndroid Build Coastguard Worker lowerAssign(llvm::cast<InstAssign>(Instr));
378*03ce13f7SAndroid Build Coastguard Worker break;
379*03ce13f7SAndroid Build Coastguard Worker case Inst::Br:
380*03ce13f7SAndroid Build Coastguard Worker lowerBr(llvm::cast<InstBr>(Instr));
381*03ce13f7SAndroid Build Coastguard Worker break;
382*03ce13f7SAndroid Build Coastguard Worker case Inst::Breakpoint:
383*03ce13f7SAndroid Build Coastguard Worker lowerBreakpoint(llvm::cast<InstBreakpoint>(Instr));
384*03ce13f7SAndroid Build Coastguard Worker break;
385*03ce13f7SAndroid Build Coastguard Worker case Inst::Call:
386*03ce13f7SAndroid Build Coastguard Worker lowerCall(llvm::cast<InstCall>(Instr));
387*03ce13f7SAndroid Build Coastguard Worker break;
388*03ce13f7SAndroid Build Coastguard Worker case Inst::Cast:
389*03ce13f7SAndroid Build Coastguard Worker lowerCast(llvm::cast<InstCast>(Instr));
390*03ce13f7SAndroid Build Coastguard Worker break;
391*03ce13f7SAndroid Build Coastguard Worker case Inst::ExtractElement:
392*03ce13f7SAndroid Build Coastguard Worker lowerExtractElement(llvm::cast<InstExtractElement>(Instr));
393*03ce13f7SAndroid Build Coastguard Worker break;
394*03ce13f7SAndroid Build Coastguard Worker case Inst::Fcmp:
395*03ce13f7SAndroid Build Coastguard Worker lowerFcmp(llvm::cast<InstFcmp>(Instr));
396*03ce13f7SAndroid Build Coastguard Worker break;
397*03ce13f7SAndroid Build Coastguard Worker case Inst::Icmp:
398*03ce13f7SAndroid Build Coastguard Worker lowerIcmp(llvm::cast<InstIcmp>(Instr));
399*03ce13f7SAndroid Build Coastguard Worker break;
400*03ce13f7SAndroid Build Coastguard Worker case Inst::InsertElement:
401*03ce13f7SAndroid Build Coastguard Worker lowerInsertElement(llvm::cast<InstInsertElement>(Instr));
402*03ce13f7SAndroid Build Coastguard Worker break;
403*03ce13f7SAndroid Build Coastguard Worker case Inst::Intrinsic: {
404*03ce13f7SAndroid Build Coastguard Worker auto *Intrinsic = llvm::cast<InstIntrinsic>(Instr);
405*03ce13f7SAndroid Build Coastguard Worker if (Intrinsic->getIntrinsicInfo().ReturnsTwice)
406*03ce13f7SAndroid Build Coastguard Worker setCallsReturnsTwice(true);
407*03ce13f7SAndroid Build Coastguard Worker lowerIntrinsic(Intrinsic);
408*03ce13f7SAndroid Build Coastguard Worker break;
409*03ce13f7SAndroid Build Coastguard Worker }
410*03ce13f7SAndroid Build Coastguard Worker case Inst::Load:
411*03ce13f7SAndroid Build Coastguard Worker lowerLoad(llvm::cast<InstLoad>(Instr));
412*03ce13f7SAndroid Build Coastguard Worker break;
413*03ce13f7SAndroid Build Coastguard Worker case Inst::Phi:
414*03ce13f7SAndroid Build Coastguard Worker lowerPhi(llvm::cast<InstPhi>(Instr));
415*03ce13f7SAndroid Build Coastguard Worker break;
416*03ce13f7SAndroid Build Coastguard Worker case Inst::Ret:
417*03ce13f7SAndroid Build Coastguard Worker lowerRet(llvm::cast<InstRet>(Instr));
418*03ce13f7SAndroid Build Coastguard Worker break;
419*03ce13f7SAndroid Build Coastguard Worker case Inst::Select:
420*03ce13f7SAndroid Build Coastguard Worker lowerSelect(llvm::cast<InstSelect>(Instr));
421*03ce13f7SAndroid Build Coastguard Worker break;
422*03ce13f7SAndroid Build Coastguard Worker case Inst::ShuffleVector:
423*03ce13f7SAndroid Build Coastguard Worker lowerShuffleVector(llvm::cast<InstShuffleVector>(Instr));
424*03ce13f7SAndroid Build Coastguard Worker break;
425*03ce13f7SAndroid Build Coastguard Worker case Inst::Store:
426*03ce13f7SAndroid Build Coastguard Worker lowerStore(llvm::cast<InstStore>(Instr));
427*03ce13f7SAndroid Build Coastguard Worker break;
428*03ce13f7SAndroid Build Coastguard Worker case Inst::Switch:
429*03ce13f7SAndroid Build Coastguard Worker lowerSwitch(llvm::cast<InstSwitch>(Instr));
430*03ce13f7SAndroid Build Coastguard Worker break;
431*03ce13f7SAndroid Build Coastguard Worker case Inst::Unreachable:
432*03ce13f7SAndroid Build Coastguard Worker lowerUnreachable(llvm::cast<InstUnreachable>(Instr));
433*03ce13f7SAndroid Build Coastguard Worker break;
434*03ce13f7SAndroid Build Coastguard Worker default:
435*03ce13f7SAndroid Build Coastguard Worker lowerOther(Instr);
436*03ce13f7SAndroid Build Coastguard Worker break;
437*03ce13f7SAndroid Build Coastguard Worker }
438*03ce13f7SAndroid Build Coastguard Worker
439*03ce13f7SAndroid Build Coastguard Worker postLower();
440*03ce13f7SAndroid Build Coastguard Worker }
441*03ce13f7SAndroid Build Coastguard Worker
442*03ce13f7SAndroid Build Coastguard Worker Context.advanceCur();
443*03ce13f7SAndroid Build Coastguard Worker Context.advanceNext();
444*03ce13f7SAndroid Build Coastguard Worker }
445*03ce13f7SAndroid Build Coastguard Worker
lowerInst(CfgNode * Node,InstList::iterator Next,InstHighLevel * Instr)446*03ce13f7SAndroid Build Coastguard Worker void TargetLowering::lowerInst(CfgNode *Node, InstList::iterator Next,
447*03ce13f7SAndroid Build Coastguard Worker InstHighLevel *Instr) {
448*03ce13f7SAndroid Build Coastguard Worker // TODO(stichnot): Consider modifying the design/implementation to avoid
449*03ce13f7SAndroid Build Coastguard Worker // multiple init() calls when using lowerInst() to lower several instructions
450*03ce13f7SAndroid Build Coastguard Worker // in the same node.
451*03ce13f7SAndroid Build Coastguard Worker Context.init(Node);
452*03ce13f7SAndroid Build Coastguard Worker Context.setNext(Next);
453*03ce13f7SAndroid Build Coastguard Worker Context.insert(Instr);
454*03ce13f7SAndroid Build Coastguard Worker --Next;
455*03ce13f7SAndroid Build Coastguard Worker assert(iteratorToInst(Next) == Instr);
456*03ce13f7SAndroid Build Coastguard Worker Context.setCur(Next);
457*03ce13f7SAndroid Build Coastguard Worker lower();
458*03ce13f7SAndroid Build Coastguard Worker }
459*03ce13f7SAndroid Build Coastguard Worker
lowerOther(const Inst * Instr)460*03ce13f7SAndroid Build Coastguard Worker void TargetLowering::lowerOther(const Inst *Instr) {
461*03ce13f7SAndroid Build Coastguard Worker (void)Instr;
462*03ce13f7SAndroid Build Coastguard Worker Func->setError("Can't lower unsupported instruction type");
463*03ce13f7SAndroid Build Coastguard Worker }
464*03ce13f7SAndroid Build Coastguard Worker
465*03ce13f7SAndroid Build Coastguard Worker // Drives register allocation, allowing all physical registers (except perhaps
466*03ce13f7SAndroid Build Coastguard Worker // for the frame pointer) to be allocated. This set of registers could
467*03ce13f7SAndroid Build Coastguard Worker // potentially be parameterized if we want to restrict registers e.g. for
468*03ce13f7SAndroid Build Coastguard Worker // performance testing.
regAlloc(RegAllocKind Kind)469*03ce13f7SAndroid Build Coastguard Worker void TargetLowering::regAlloc(RegAllocKind Kind) {
470*03ce13f7SAndroid Build Coastguard Worker TimerMarker T(TimerStack::TT_regAlloc, Func);
471*03ce13f7SAndroid Build Coastguard Worker LinearScan LinearScan(Func);
472*03ce13f7SAndroid Build Coastguard Worker RegSetMask RegInclude = RegSet_None;
473*03ce13f7SAndroid Build Coastguard Worker RegSetMask RegExclude = RegSet_None;
474*03ce13f7SAndroid Build Coastguard Worker RegInclude |= RegSet_CallerSave;
475*03ce13f7SAndroid Build Coastguard Worker RegInclude |= RegSet_CalleeSave;
476*03ce13f7SAndroid Build Coastguard Worker if (hasFramePointer())
477*03ce13f7SAndroid Build Coastguard Worker RegExclude |= RegSet_FramePointer;
478*03ce13f7SAndroid Build Coastguard Worker SmallBitVector RegMask = getRegisterSet(RegInclude, RegExclude);
479*03ce13f7SAndroid Build Coastguard Worker bool Repeat = (Kind == RAK_Global && getFlags().getRepeatRegAlloc());
480*03ce13f7SAndroid Build Coastguard Worker CfgSet<Variable *> EmptySet;
481*03ce13f7SAndroid Build Coastguard Worker do {
482*03ce13f7SAndroid Build Coastguard Worker LinearScan.init(Kind, EmptySet);
483*03ce13f7SAndroid Build Coastguard Worker LinearScan.scan(RegMask);
484*03ce13f7SAndroid Build Coastguard Worker if (!LinearScan.hasEvictions())
485*03ce13f7SAndroid Build Coastguard Worker Repeat = false;
486*03ce13f7SAndroid Build Coastguard Worker Kind = RAK_SecondChance;
487*03ce13f7SAndroid Build Coastguard Worker } while (Repeat);
488*03ce13f7SAndroid Build Coastguard Worker // TODO(stichnot): Run the register allocator one more time to do stack slot
489*03ce13f7SAndroid Build Coastguard Worker // coalescing. The idea would be to initialize the Unhandled list with the
490*03ce13f7SAndroid Build Coastguard Worker // set of Variables that have no register and a non-empty live range, and
491*03ce13f7SAndroid Build Coastguard Worker // model an infinite number of registers. Maybe use the register aliasing
492*03ce13f7SAndroid Build Coastguard Worker // mechanism to get better packing of narrower slots.
493*03ce13f7SAndroid Build Coastguard Worker if (getFlags().getSplitGlobalVars())
494*03ce13f7SAndroid Build Coastguard Worker postRegallocSplitting(RegMask);
495*03ce13f7SAndroid Build Coastguard Worker }
496*03ce13f7SAndroid Build Coastguard Worker
497*03ce13f7SAndroid Build Coastguard Worker namespace {
getInstructionsInRange(CfgNode * Node,InstNumberT Start,InstNumberT End)498*03ce13f7SAndroid Build Coastguard Worker CfgVector<Inst *> getInstructionsInRange(CfgNode *Node, InstNumberT Start,
499*03ce13f7SAndroid Build Coastguard Worker InstNumberT End) {
500*03ce13f7SAndroid Build Coastguard Worker CfgVector<Inst *> Result;
501*03ce13f7SAndroid Build Coastguard Worker bool Started = false;
502*03ce13f7SAndroid Build Coastguard Worker auto Process = [&](InstList &Insts) {
503*03ce13f7SAndroid Build Coastguard Worker for (auto &Instr : Insts) {
504*03ce13f7SAndroid Build Coastguard Worker if (Instr.isDeleted()) {
505*03ce13f7SAndroid Build Coastguard Worker continue;
506*03ce13f7SAndroid Build Coastguard Worker }
507*03ce13f7SAndroid Build Coastguard Worker if (Instr.getNumber() == Start) {
508*03ce13f7SAndroid Build Coastguard Worker Started = true;
509*03ce13f7SAndroid Build Coastguard Worker }
510*03ce13f7SAndroid Build Coastguard Worker if (Started) {
511*03ce13f7SAndroid Build Coastguard Worker Result.emplace_back(&Instr);
512*03ce13f7SAndroid Build Coastguard Worker }
513*03ce13f7SAndroid Build Coastguard Worker if (Instr.getNumber() == End) {
514*03ce13f7SAndroid Build Coastguard Worker break;
515*03ce13f7SAndroid Build Coastguard Worker }
516*03ce13f7SAndroid Build Coastguard Worker }
517*03ce13f7SAndroid Build Coastguard Worker };
518*03ce13f7SAndroid Build Coastguard Worker Process(Node->getPhis());
519*03ce13f7SAndroid Build Coastguard Worker Process(Node->getInsts());
520*03ce13f7SAndroid Build Coastguard Worker // TODO(manasijm): Investigate why checking >= End significantly changes
521*03ce13f7SAndroid Build Coastguard Worker // output. Should not happen when renumbering produces monotonically
522*03ce13f7SAndroid Build Coastguard Worker // increasing instruction numbers and live ranges begin and end on non-deleted
523*03ce13f7SAndroid Build Coastguard Worker // instructions.
524*03ce13f7SAndroid Build Coastguard Worker return Result;
525*03ce13f7SAndroid Build Coastguard Worker }
526*03ce13f7SAndroid Build Coastguard Worker } // namespace
527*03ce13f7SAndroid Build Coastguard Worker
postRegallocSplitting(const SmallBitVector & RegMask)528*03ce13f7SAndroid Build Coastguard Worker void TargetLowering::postRegallocSplitting(const SmallBitVector &RegMask) {
529*03ce13f7SAndroid Build Coastguard Worker // Splits the live ranges of global(/multi block) variables and runs the
530*03ce13f7SAndroid Build Coastguard Worker // register allocator to find registers for as many of the new variables as
531*03ce13f7SAndroid Build Coastguard Worker // possible.
532*03ce13f7SAndroid Build Coastguard Worker // TODO(manasijm): Merge the small liveranges back into multi-block ones when
533*03ce13f7SAndroid Build Coastguard Worker // the variables get the same register. This will reduce the amount of new
534*03ce13f7SAndroid Build Coastguard Worker // instructions inserted. This might involve a full dataflow analysis.
535*03ce13f7SAndroid Build Coastguard Worker // Also, modify the preference mechanism in the register allocator to match.
536*03ce13f7SAndroid Build Coastguard Worker
537*03ce13f7SAndroid Build Coastguard Worker TimerMarker _(TimerStack::TT_splitGlobalVars, Func);
538*03ce13f7SAndroid Build Coastguard Worker CfgSet<Variable *> SplitCandidates;
539*03ce13f7SAndroid Build Coastguard Worker
540*03ce13f7SAndroid Build Coastguard Worker // Find variables that do not have registers but are allowed to. Also skip
541*03ce13f7SAndroid Build Coastguard Worker // variables with single segment live ranges as they are not split further in
542*03ce13f7SAndroid Build Coastguard Worker // this function.
543*03ce13f7SAndroid Build Coastguard Worker for (Variable *Var : Func->getVariables()) {
544*03ce13f7SAndroid Build Coastguard Worker if (!Var->mustNotHaveReg() && !Var->hasReg()) {
545*03ce13f7SAndroid Build Coastguard Worker if (Var->getLiveRange().getNumSegments() > 1)
546*03ce13f7SAndroid Build Coastguard Worker SplitCandidates.insert(Var);
547*03ce13f7SAndroid Build Coastguard Worker }
548*03ce13f7SAndroid Build Coastguard Worker }
549*03ce13f7SAndroid Build Coastguard Worker if (SplitCandidates.empty())
550*03ce13f7SAndroid Build Coastguard Worker return;
551*03ce13f7SAndroid Build Coastguard Worker
552*03ce13f7SAndroid Build Coastguard Worker CfgSet<Variable *> ExtraVars;
553*03ce13f7SAndroid Build Coastguard Worker
554*03ce13f7SAndroid Build Coastguard Worker struct UseInfo {
555*03ce13f7SAndroid Build Coastguard Worker Variable *Replacing = nullptr;
556*03ce13f7SAndroid Build Coastguard Worker Inst *FirstUse = nullptr;
557*03ce13f7SAndroid Build Coastguard Worker Inst *LastDef = nullptr;
558*03ce13f7SAndroid Build Coastguard Worker SizeT UseCount = 0;
559*03ce13f7SAndroid Build Coastguard Worker };
560*03ce13f7SAndroid Build Coastguard Worker CfgUnorderedMap<Variable *, UseInfo> VarInfo;
561*03ce13f7SAndroid Build Coastguard Worker // Split the live ranges of the viable variables by node.
562*03ce13f7SAndroid Build Coastguard Worker // Compute metadata (UseInfo) for each of the resulting variables.
563*03ce13f7SAndroid Build Coastguard Worker for (auto *Var : SplitCandidates) {
564*03ce13f7SAndroid Build Coastguard Worker for (auto &Segment : Var->getLiveRange().getSegments()) {
565*03ce13f7SAndroid Build Coastguard Worker UseInfo Info;
566*03ce13f7SAndroid Build Coastguard Worker Info.Replacing = Var;
567*03ce13f7SAndroid Build Coastguard Worker auto *Node = Var->getLiveRange().getNodeForSegment(Segment.first);
568*03ce13f7SAndroid Build Coastguard Worker
569*03ce13f7SAndroid Build Coastguard Worker for (auto *Instr :
570*03ce13f7SAndroid Build Coastguard Worker getInstructionsInRange(Node, Segment.first, Segment.second)) {
571*03ce13f7SAndroid Build Coastguard Worker for (SizeT i = 0; i < Instr->getSrcSize(); ++i) {
572*03ce13f7SAndroid Build Coastguard Worker // It's safe to iterate over the top-level src operands rather than
573*03ce13f7SAndroid Build Coastguard Worker // using FOREACH_VAR_IN_INST(), because any variables inside e.g.
574*03ce13f7SAndroid Build Coastguard Worker // mem operands should already have registers.
575*03ce13f7SAndroid Build Coastguard Worker if (auto *Var = llvm::dyn_cast<Variable>(Instr->getSrc(i))) {
576*03ce13f7SAndroid Build Coastguard Worker if (Var == Info.Replacing) {
577*03ce13f7SAndroid Build Coastguard Worker if (Info.FirstUse == nullptr && !llvm::isa<InstPhi>(Instr)) {
578*03ce13f7SAndroid Build Coastguard Worker Info.FirstUse = Instr;
579*03ce13f7SAndroid Build Coastguard Worker }
580*03ce13f7SAndroid Build Coastguard Worker Info.UseCount++;
581*03ce13f7SAndroid Build Coastguard Worker }
582*03ce13f7SAndroid Build Coastguard Worker }
583*03ce13f7SAndroid Build Coastguard Worker }
584*03ce13f7SAndroid Build Coastguard Worker if (Instr->getDest() == Info.Replacing && !llvm::isa<InstPhi>(Instr)) {
585*03ce13f7SAndroid Build Coastguard Worker Info.LastDef = Instr;
586*03ce13f7SAndroid Build Coastguard Worker }
587*03ce13f7SAndroid Build Coastguard Worker }
588*03ce13f7SAndroid Build Coastguard Worker
589*03ce13f7SAndroid Build Coastguard Worker static constexpr SizeT MinUseThreshold = 3;
590*03ce13f7SAndroid Build Coastguard Worker // Skip if variable has less than `MinUseThreshold` uses in the segment.
591*03ce13f7SAndroid Build Coastguard Worker if (Info.UseCount < MinUseThreshold)
592*03ce13f7SAndroid Build Coastguard Worker continue;
593*03ce13f7SAndroid Build Coastguard Worker
594*03ce13f7SAndroid Build Coastguard Worker if (!Info.FirstUse && !Info.LastDef) {
595*03ce13f7SAndroid Build Coastguard Worker continue;
596*03ce13f7SAndroid Build Coastguard Worker }
597*03ce13f7SAndroid Build Coastguard Worker
598*03ce13f7SAndroid Build Coastguard Worker LiveRange LR;
599*03ce13f7SAndroid Build Coastguard Worker LR.addSegment(Segment);
600*03ce13f7SAndroid Build Coastguard Worker Variable *NewVar = Func->makeVariable(Var->getType());
601*03ce13f7SAndroid Build Coastguard Worker
602*03ce13f7SAndroid Build Coastguard Worker NewVar->setLiveRange(LR);
603*03ce13f7SAndroid Build Coastguard Worker
604*03ce13f7SAndroid Build Coastguard Worker VarInfo[NewVar] = Info;
605*03ce13f7SAndroid Build Coastguard Worker
606*03ce13f7SAndroid Build Coastguard Worker ExtraVars.insert(NewVar);
607*03ce13f7SAndroid Build Coastguard Worker }
608*03ce13f7SAndroid Build Coastguard Worker }
609*03ce13f7SAndroid Build Coastguard Worker // Run the register allocator with all these new variables included
610*03ce13f7SAndroid Build Coastguard Worker LinearScan RegAlloc(Func);
611*03ce13f7SAndroid Build Coastguard Worker RegAlloc.init(RAK_Global, SplitCandidates);
612*03ce13f7SAndroid Build Coastguard Worker RegAlloc.scan(RegMask);
613*03ce13f7SAndroid Build Coastguard Worker
614*03ce13f7SAndroid Build Coastguard Worker // Modify the Cfg to use the new variables that now have registers.
615*03ce13f7SAndroid Build Coastguard Worker for (auto *ExtraVar : ExtraVars) {
616*03ce13f7SAndroid Build Coastguard Worker if (!ExtraVar->hasReg()) {
617*03ce13f7SAndroid Build Coastguard Worker continue;
618*03ce13f7SAndroid Build Coastguard Worker }
619*03ce13f7SAndroid Build Coastguard Worker
620*03ce13f7SAndroid Build Coastguard Worker auto &Info = VarInfo[ExtraVar];
621*03ce13f7SAndroid Build Coastguard Worker
622*03ce13f7SAndroid Build Coastguard Worker assert(ExtraVar->getLiveRange().getSegments().size() == 1);
623*03ce13f7SAndroid Build Coastguard Worker auto Segment = ExtraVar->getLiveRange().getSegments()[0];
624*03ce13f7SAndroid Build Coastguard Worker
625*03ce13f7SAndroid Build Coastguard Worker auto *Node =
626*03ce13f7SAndroid Build Coastguard Worker Info.Replacing->getLiveRange().getNodeForSegment(Segment.first);
627*03ce13f7SAndroid Build Coastguard Worker
628*03ce13f7SAndroid Build Coastguard Worker auto RelevantInsts =
629*03ce13f7SAndroid Build Coastguard Worker getInstructionsInRange(Node, Segment.first, Segment.second);
630*03ce13f7SAndroid Build Coastguard Worker
631*03ce13f7SAndroid Build Coastguard Worker if (RelevantInsts.empty())
632*03ce13f7SAndroid Build Coastguard Worker continue;
633*03ce13f7SAndroid Build Coastguard Worker
634*03ce13f7SAndroid Build Coastguard Worker // Replace old variables
635*03ce13f7SAndroid Build Coastguard Worker for (auto *Instr : RelevantInsts) {
636*03ce13f7SAndroid Build Coastguard Worker if (llvm::isa<InstPhi>(Instr))
637*03ce13f7SAndroid Build Coastguard Worker continue;
638*03ce13f7SAndroid Build Coastguard Worker // TODO(manasijm): Figure out how to safely enable replacing phi dest
639*03ce13f7SAndroid Build Coastguard Worker // variables. The issue is that we can not insert low level mov
640*03ce13f7SAndroid Build Coastguard Worker // instructions into the PhiList.
641*03ce13f7SAndroid Build Coastguard Worker for (SizeT i = 0; i < Instr->getSrcSize(); ++i) {
642*03ce13f7SAndroid Build Coastguard Worker // FOREACH_VAR_IN_INST() not needed. Same logic as above.
643*03ce13f7SAndroid Build Coastguard Worker if (auto *Var = llvm::dyn_cast<Variable>(Instr->getSrc(i))) {
644*03ce13f7SAndroid Build Coastguard Worker if (Var == Info.Replacing) {
645*03ce13f7SAndroid Build Coastguard Worker Instr->replaceSource(i, ExtraVar);
646*03ce13f7SAndroid Build Coastguard Worker }
647*03ce13f7SAndroid Build Coastguard Worker }
648*03ce13f7SAndroid Build Coastguard Worker }
649*03ce13f7SAndroid Build Coastguard Worker if (Instr->getDest() == Info.Replacing) {
650*03ce13f7SAndroid Build Coastguard Worker Instr->replaceDest(ExtraVar);
651*03ce13f7SAndroid Build Coastguard Worker }
652*03ce13f7SAndroid Build Coastguard Worker }
653*03ce13f7SAndroid Build Coastguard Worker
654*03ce13f7SAndroid Build Coastguard Worker assert(Info.FirstUse != Info.LastDef);
655*03ce13f7SAndroid Build Coastguard Worker assert(Info.FirstUse || Info.LastDef);
656*03ce13f7SAndroid Build Coastguard Worker
657*03ce13f7SAndroid Build Coastguard Worker // Insert spill code
658*03ce13f7SAndroid Build Coastguard Worker if (Info.FirstUse != nullptr) {
659*03ce13f7SAndroid Build Coastguard Worker auto *NewInst =
660*03ce13f7SAndroid Build Coastguard Worker Func->getTarget()->createLoweredMove(ExtraVar, Info.Replacing);
661*03ce13f7SAndroid Build Coastguard Worker Node->getInsts().insert(instToIterator(Info.FirstUse), NewInst);
662*03ce13f7SAndroid Build Coastguard Worker }
663*03ce13f7SAndroid Build Coastguard Worker if (Info.LastDef != nullptr) {
664*03ce13f7SAndroid Build Coastguard Worker auto *NewInst =
665*03ce13f7SAndroid Build Coastguard Worker Func->getTarget()->createLoweredMove(Info.Replacing, ExtraVar);
666*03ce13f7SAndroid Build Coastguard Worker Node->getInsts().insertAfter(instToIterator(Info.LastDef), NewInst);
667*03ce13f7SAndroid Build Coastguard Worker }
668*03ce13f7SAndroid Build Coastguard Worker }
669*03ce13f7SAndroid Build Coastguard Worker }
670*03ce13f7SAndroid Build Coastguard Worker
markRedefinitions()671*03ce13f7SAndroid Build Coastguard Worker void TargetLowering::markRedefinitions() {
672*03ce13f7SAndroid Build Coastguard Worker // Find (non-SSA) instructions where the Dest variable appears in some source
673*03ce13f7SAndroid Build Coastguard Worker // operand, and set the IsDestRedefined flag to keep liveness analysis
674*03ce13f7SAndroid Build Coastguard Worker // consistent.
675*03ce13f7SAndroid Build Coastguard Worker for (auto Instr = Context.getCur(), E = Context.getNext(); Instr != E;
676*03ce13f7SAndroid Build Coastguard Worker ++Instr) {
677*03ce13f7SAndroid Build Coastguard Worker if (Instr->isDeleted())
678*03ce13f7SAndroid Build Coastguard Worker continue;
679*03ce13f7SAndroid Build Coastguard Worker Variable *Dest = Instr->getDest();
680*03ce13f7SAndroid Build Coastguard Worker if (Dest == nullptr)
681*03ce13f7SAndroid Build Coastguard Worker continue;
682*03ce13f7SAndroid Build Coastguard Worker FOREACH_VAR_IN_INST(Var, *Instr) {
683*03ce13f7SAndroid Build Coastguard Worker if (Var == Dest) {
684*03ce13f7SAndroid Build Coastguard Worker Instr->setDestRedefined();
685*03ce13f7SAndroid Build Coastguard Worker break;
686*03ce13f7SAndroid Build Coastguard Worker }
687*03ce13f7SAndroid Build Coastguard Worker }
688*03ce13f7SAndroid Build Coastguard Worker }
689*03ce13f7SAndroid Build Coastguard Worker }
690*03ce13f7SAndroid Build Coastguard Worker
addFakeDefUses(const Inst * Instr)691*03ce13f7SAndroid Build Coastguard Worker void TargetLowering::addFakeDefUses(const Inst *Instr) {
692*03ce13f7SAndroid Build Coastguard Worker FOREACH_VAR_IN_INST(Var, *Instr) {
693*03ce13f7SAndroid Build Coastguard Worker if (auto *Var64 = llvm::dyn_cast<Variable64On32>(Var)) {
694*03ce13f7SAndroid Build Coastguard Worker Context.insert<InstFakeUse>(Var64->getLo());
695*03ce13f7SAndroid Build Coastguard Worker Context.insert<InstFakeUse>(Var64->getHi());
696*03ce13f7SAndroid Build Coastguard Worker } else if (auto *VarVec = llvm::dyn_cast<VariableVecOn32>(Var)) {
697*03ce13f7SAndroid Build Coastguard Worker for (Variable *Var : VarVec->getContainers()) {
698*03ce13f7SAndroid Build Coastguard Worker Context.insert<InstFakeUse>(Var);
699*03ce13f7SAndroid Build Coastguard Worker }
700*03ce13f7SAndroid Build Coastguard Worker } else {
701*03ce13f7SAndroid Build Coastguard Worker Context.insert<InstFakeUse>(Var);
702*03ce13f7SAndroid Build Coastguard Worker }
703*03ce13f7SAndroid Build Coastguard Worker }
704*03ce13f7SAndroid Build Coastguard Worker Variable *Dest = Instr->getDest();
705*03ce13f7SAndroid Build Coastguard Worker if (Dest == nullptr)
706*03ce13f7SAndroid Build Coastguard Worker return;
707*03ce13f7SAndroid Build Coastguard Worker if (auto *Var64 = llvm::dyn_cast<Variable64On32>(Dest)) {
708*03ce13f7SAndroid Build Coastguard Worker Context.insert<InstFakeDef>(Var64->getLo());
709*03ce13f7SAndroid Build Coastguard Worker Context.insert<InstFakeDef>(Var64->getHi());
710*03ce13f7SAndroid Build Coastguard Worker } else if (auto *VarVec = llvm::dyn_cast<VariableVecOn32>(Dest)) {
711*03ce13f7SAndroid Build Coastguard Worker for (Variable *Var : VarVec->getContainers()) {
712*03ce13f7SAndroid Build Coastguard Worker Context.insert<InstFakeDef>(Var);
713*03ce13f7SAndroid Build Coastguard Worker }
714*03ce13f7SAndroid Build Coastguard Worker } else {
715*03ce13f7SAndroid Build Coastguard Worker Context.insert<InstFakeDef>(Dest);
716*03ce13f7SAndroid Build Coastguard Worker }
717*03ce13f7SAndroid Build Coastguard Worker }
718*03ce13f7SAndroid Build Coastguard Worker
sortVarsByAlignment(VarList & Dest,const VarList & Source) const719*03ce13f7SAndroid Build Coastguard Worker void TargetLowering::sortVarsByAlignment(VarList &Dest,
720*03ce13f7SAndroid Build Coastguard Worker const VarList &Source) const {
721*03ce13f7SAndroid Build Coastguard Worker Dest = Source;
722*03ce13f7SAndroid Build Coastguard Worker // Instead of std::sort, we could do a bucket sort with log2(alignment) as
723*03ce13f7SAndroid Build Coastguard Worker // the buckets, if performance is an issue.
724*03ce13f7SAndroid Build Coastguard Worker std::sort(Dest.begin(), Dest.end(),
725*03ce13f7SAndroid Build Coastguard Worker [this](const Variable *V1, const Variable *V2) {
726*03ce13f7SAndroid Build Coastguard Worker const size_t WidthV1 = typeWidthInBytesOnStack(V1->getType());
727*03ce13f7SAndroid Build Coastguard Worker const size_t WidthV2 = typeWidthInBytesOnStack(V2->getType());
728*03ce13f7SAndroid Build Coastguard Worker if (WidthV1 == WidthV2)
729*03ce13f7SAndroid Build Coastguard Worker return V1->getIndex() < V2->getIndex();
730*03ce13f7SAndroid Build Coastguard Worker return WidthV1 > WidthV2;
731*03ce13f7SAndroid Build Coastguard Worker });
732*03ce13f7SAndroid Build Coastguard Worker }
733*03ce13f7SAndroid Build Coastguard Worker
getVarStackSlotParams(VarList & SortedSpilledVariables,SmallBitVector & RegsUsed,size_t * GlobalsSize,size_t * SpillAreaSizeBytes,uint32_t * SpillAreaAlignmentBytes,uint32_t * LocalsSlotsAlignmentBytes,std::function<bool (Variable *)> TargetVarHook)734*03ce13f7SAndroid Build Coastguard Worker void TargetLowering::getVarStackSlotParams(
735*03ce13f7SAndroid Build Coastguard Worker VarList &SortedSpilledVariables, SmallBitVector &RegsUsed,
736*03ce13f7SAndroid Build Coastguard Worker size_t *GlobalsSize, size_t *SpillAreaSizeBytes,
737*03ce13f7SAndroid Build Coastguard Worker uint32_t *SpillAreaAlignmentBytes, uint32_t *LocalsSlotsAlignmentBytes,
738*03ce13f7SAndroid Build Coastguard Worker std::function<bool(Variable *)> TargetVarHook) {
739*03ce13f7SAndroid Build Coastguard Worker const VariablesMetadata *VMetadata = Func->getVMetadata();
740*03ce13f7SAndroid Build Coastguard Worker BitVector IsVarReferenced(Func->getNumVariables());
741*03ce13f7SAndroid Build Coastguard Worker for (CfgNode *Node : Func->getNodes()) {
742*03ce13f7SAndroid Build Coastguard Worker for (Inst &Instr : Node->getInsts()) {
743*03ce13f7SAndroid Build Coastguard Worker if (Instr.isDeleted())
744*03ce13f7SAndroid Build Coastguard Worker continue;
745*03ce13f7SAndroid Build Coastguard Worker if (const Variable *Var = Instr.getDest())
746*03ce13f7SAndroid Build Coastguard Worker IsVarReferenced[Var->getIndex()] = true;
747*03ce13f7SAndroid Build Coastguard Worker FOREACH_VAR_IN_INST(Var, Instr) {
748*03ce13f7SAndroid Build Coastguard Worker IsVarReferenced[Var->getIndex()] = true;
749*03ce13f7SAndroid Build Coastguard Worker }
750*03ce13f7SAndroid Build Coastguard Worker }
751*03ce13f7SAndroid Build Coastguard Worker }
752*03ce13f7SAndroid Build Coastguard Worker
753*03ce13f7SAndroid Build Coastguard Worker // If SimpleCoalescing is false, each variable without a register gets its
754*03ce13f7SAndroid Build Coastguard Worker // own unique stack slot, which leads to large stack frames. If
755*03ce13f7SAndroid Build Coastguard Worker // SimpleCoalescing is true, then each "global" variable without a register
756*03ce13f7SAndroid Build Coastguard Worker // gets its own slot, but "local" variable slots are reused across basic
757*03ce13f7SAndroid Build Coastguard Worker // blocks. E.g., if A and B are local to block 1 and C is local to block 2,
758*03ce13f7SAndroid Build Coastguard Worker // then C may share a slot with A or B.
759*03ce13f7SAndroid Build Coastguard Worker //
760*03ce13f7SAndroid Build Coastguard Worker // We cannot coalesce stack slots if this function calls a "returns twice"
761*03ce13f7SAndroid Build Coastguard Worker // function. In that case, basic blocks may be revisited, and variables local
762*03ce13f7SAndroid Build Coastguard Worker // to those basic blocks are actually live until after the called function
763*03ce13f7SAndroid Build Coastguard Worker // returns a second time.
764*03ce13f7SAndroid Build Coastguard Worker const bool SimpleCoalescing = !callsReturnsTwice();
765*03ce13f7SAndroid Build Coastguard Worker
766*03ce13f7SAndroid Build Coastguard Worker CfgVector<size_t> LocalsSize(Func->getNumNodes());
767*03ce13f7SAndroid Build Coastguard Worker const VarList &Variables = Func->getVariables();
768*03ce13f7SAndroid Build Coastguard Worker VarList SpilledVariables;
769*03ce13f7SAndroid Build Coastguard Worker for (Variable *Var : Variables) {
770*03ce13f7SAndroid Build Coastguard Worker if (Var->hasReg()) {
771*03ce13f7SAndroid Build Coastguard Worker // Don't consider a rematerializable variable to be an actual register use
772*03ce13f7SAndroid Build Coastguard Worker // (specifically of the frame pointer). Otherwise, the prolog may decide
773*03ce13f7SAndroid Build Coastguard Worker // to save the frame pointer twice - once because of the explicit need for
774*03ce13f7SAndroid Build Coastguard Worker // a frame pointer, and once because of an active use of a callee-save
775*03ce13f7SAndroid Build Coastguard Worker // register.
776*03ce13f7SAndroid Build Coastguard Worker if (!Var->isRematerializable())
777*03ce13f7SAndroid Build Coastguard Worker RegsUsed[Var->getRegNum()] = true;
778*03ce13f7SAndroid Build Coastguard Worker continue;
779*03ce13f7SAndroid Build Coastguard Worker }
780*03ce13f7SAndroid Build Coastguard Worker // An argument either does not need a stack slot (if passed in a register)
781*03ce13f7SAndroid Build Coastguard Worker // or already has one (if passed on the stack).
782*03ce13f7SAndroid Build Coastguard Worker if (Var->getIsArg()) {
783*03ce13f7SAndroid Build Coastguard Worker if (!Var->hasReg()) {
784*03ce13f7SAndroid Build Coastguard Worker assert(!Var->hasStackOffset());
785*03ce13f7SAndroid Build Coastguard Worker Var->setHasStackOffset();
786*03ce13f7SAndroid Build Coastguard Worker }
787*03ce13f7SAndroid Build Coastguard Worker continue;
788*03ce13f7SAndroid Build Coastguard Worker }
789*03ce13f7SAndroid Build Coastguard Worker // An unreferenced variable doesn't need a stack slot.
790*03ce13f7SAndroid Build Coastguard Worker if (!IsVarReferenced[Var->getIndex()])
791*03ce13f7SAndroid Build Coastguard Worker continue;
792*03ce13f7SAndroid Build Coastguard Worker // Check a target-specific variable (it may end up sharing stack slots) and
793*03ce13f7SAndroid Build Coastguard Worker // not need accounting here.
794*03ce13f7SAndroid Build Coastguard Worker if (TargetVarHook(Var))
795*03ce13f7SAndroid Build Coastguard Worker continue;
796*03ce13f7SAndroid Build Coastguard Worker assert(!Var->hasStackOffset());
797*03ce13f7SAndroid Build Coastguard Worker Var->setHasStackOffset();
798*03ce13f7SAndroid Build Coastguard Worker SpilledVariables.push_back(Var);
799*03ce13f7SAndroid Build Coastguard Worker }
800*03ce13f7SAndroid Build Coastguard Worker
801*03ce13f7SAndroid Build Coastguard Worker SortedSpilledVariables.reserve(SpilledVariables.size());
802*03ce13f7SAndroid Build Coastguard Worker sortVarsByAlignment(SortedSpilledVariables, SpilledVariables);
803*03ce13f7SAndroid Build Coastguard Worker
804*03ce13f7SAndroid Build Coastguard Worker for (Variable *Var : SortedSpilledVariables) {
805*03ce13f7SAndroid Build Coastguard Worker size_t Increment = typeWidthInBytesOnStack(Var->getType());
806*03ce13f7SAndroid Build Coastguard Worker // We have sorted by alignment, so the first variable we encounter that is
807*03ce13f7SAndroid Build Coastguard Worker // located in each area determines the max alignment for the area.
808*03ce13f7SAndroid Build Coastguard Worker if (!*SpillAreaAlignmentBytes)
809*03ce13f7SAndroid Build Coastguard Worker *SpillAreaAlignmentBytes = Increment;
810*03ce13f7SAndroid Build Coastguard Worker if (SimpleCoalescing && VMetadata->isTracked(Var)) {
811*03ce13f7SAndroid Build Coastguard Worker if (VMetadata->isMultiBlock(Var)) {
812*03ce13f7SAndroid Build Coastguard Worker *GlobalsSize += Increment;
813*03ce13f7SAndroid Build Coastguard Worker } else {
814*03ce13f7SAndroid Build Coastguard Worker SizeT NodeIndex = VMetadata->getLocalUseNode(Var)->getIndex();
815*03ce13f7SAndroid Build Coastguard Worker LocalsSize[NodeIndex] += Increment;
816*03ce13f7SAndroid Build Coastguard Worker if (LocalsSize[NodeIndex] > *SpillAreaSizeBytes)
817*03ce13f7SAndroid Build Coastguard Worker *SpillAreaSizeBytes = LocalsSize[NodeIndex];
818*03ce13f7SAndroid Build Coastguard Worker if (!*LocalsSlotsAlignmentBytes)
819*03ce13f7SAndroid Build Coastguard Worker *LocalsSlotsAlignmentBytes = Increment;
820*03ce13f7SAndroid Build Coastguard Worker }
821*03ce13f7SAndroid Build Coastguard Worker } else {
822*03ce13f7SAndroid Build Coastguard Worker *SpillAreaSizeBytes += Increment;
823*03ce13f7SAndroid Build Coastguard Worker }
824*03ce13f7SAndroid Build Coastguard Worker }
825*03ce13f7SAndroid Build Coastguard Worker // For testing legalization of large stack offsets on targets with limited
826*03ce13f7SAndroid Build Coastguard Worker // offset bits in instruction encodings, add some padding.
827*03ce13f7SAndroid Build Coastguard Worker *SpillAreaSizeBytes += getFlags().getTestStackExtra();
828*03ce13f7SAndroid Build Coastguard Worker }
829*03ce13f7SAndroid Build Coastguard Worker
alignStackSpillAreas(uint32_t SpillAreaStartOffset,uint32_t SpillAreaAlignmentBytes,size_t GlobalsSize,uint32_t LocalsSlotsAlignmentBytes,uint32_t * SpillAreaPaddingBytes,uint32_t * LocalsSlotsPaddingBytes)830*03ce13f7SAndroid Build Coastguard Worker void TargetLowering::alignStackSpillAreas(uint32_t SpillAreaStartOffset,
831*03ce13f7SAndroid Build Coastguard Worker uint32_t SpillAreaAlignmentBytes,
832*03ce13f7SAndroid Build Coastguard Worker size_t GlobalsSize,
833*03ce13f7SAndroid Build Coastguard Worker uint32_t LocalsSlotsAlignmentBytes,
834*03ce13f7SAndroid Build Coastguard Worker uint32_t *SpillAreaPaddingBytes,
835*03ce13f7SAndroid Build Coastguard Worker uint32_t *LocalsSlotsPaddingBytes) {
836*03ce13f7SAndroid Build Coastguard Worker if (SpillAreaAlignmentBytes) {
837*03ce13f7SAndroid Build Coastguard Worker uint32_t PaddingStart = SpillAreaStartOffset;
838*03ce13f7SAndroid Build Coastguard Worker uint32_t SpillAreaStart =
839*03ce13f7SAndroid Build Coastguard Worker Utils::applyAlignment(PaddingStart, SpillAreaAlignmentBytes);
840*03ce13f7SAndroid Build Coastguard Worker *SpillAreaPaddingBytes = SpillAreaStart - PaddingStart;
841*03ce13f7SAndroid Build Coastguard Worker }
842*03ce13f7SAndroid Build Coastguard Worker
843*03ce13f7SAndroid Build Coastguard Worker // If there are separate globals and locals areas, make sure the locals area
844*03ce13f7SAndroid Build Coastguard Worker // is aligned by padding the end of the globals area.
845*03ce13f7SAndroid Build Coastguard Worker if (LocalsSlotsAlignmentBytes) {
846*03ce13f7SAndroid Build Coastguard Worker uint32_t GlobalsAndSubsequentPaddingSize = GlobalsSize;
847*03ce13f7SAndroid Build Coastguard Worker GlobalsAndSubsequentPaddingSize =
848*03ce13f7SAndroid Build Coastguard Worker Utils::applyAlignment(GlobalsSize, LocalsSlotsAlignmentBytes);
849*03ce13f7SAndroid Build Coastguard Worker *LocalsSlotsPaddingBytes = GlobalsAndSubsequentPaddingSize - GlobalsSize;
850*03ce13f7SAndroid Build Coastguard Worker }
851*03ce13f7SAndroid Build Coastguard Worker }
852*03ce13f7SAndroid Build Coastguard Worker
assignVarStackSlots(VarList & SortedSpilledVariables,size_t SpillAreaPaddingBytes,size_t SpillAreaSizeBytes,size_t GlobalsAndSubsequentPaddingSize,bool UsesFramePointer)853*03ce13f7SAndroid Build Coastguard Worker void TargetLowering::assignVarStackSlots(VarList &SortedSpilledVariables,
854*03ce13f7SAndroid Build Coastguard Worker size_t SpillAreaPaddingBytes,
855*03ce13f7SAndroid Build Coastguard Worker size_t SpillAreaSizeBytes,
856*03ce13f7SAndroid Build Coastguard Worker size_t GlobalsAndSubsequentPaddingSize,
857*03ce13f7SAndroid Build Coastguard Worker bool UsesFramePointer) {
858*03ce13f7SAndroid Build Coastguard Worker const VariablesMetadata *VMetadata = Func->getVMetadata();
859*03ce13f7SAndroid Build Coastguard Worker // For testing legalization of large stack offsets on targets with limited
860*03ce13f7SAndroid Build Coastguard Worker // offset bits in instruction encodings, add some padding. This assumes that
861*03ce13f7SAndroid Build Coastguard Worker // SpillAreaSizeBytes has accounted for the extra test padding. When
862*03ce13f7SAndroid Build Coastguard Worker // UseFramePointer is true, the offset depends on the padding, not just the
863*03ce13f7SAndroid Build Coastguard Worker // SpillAreaSizeBytes. On the other hand, when UseFramePointer is false, the
864*03ce13f7SAndroid Build Coastguard Worker // offsets depend on the gap between SpillAreaSizeBytes and
865*03ce13f7SAndroid Build Coastguard Worker // SpillAreaPaddingBytes, so we don't increment that.
866*03ce13f7SAndroid Build Coastguard Worker size_t TestPadding = getFlags().getTestStackExtra();
867*03ce13f7SAndroid Build Coastguard Worker if (UsesFramePointer)
868*03ce13f7SAndroid Build Coastguard Worker SpillAreaPaddingBytes += TestPadding;
869*03ce13f7SAndroid Build Coastguard Worker size_t GlobalsSpaceUsed = SpillAreaPaddingBytes;
870*03ce13f7SAndroid Build Coastguard Worker size_t NextStackOffset = SpillAreaPaddingBytes;
871*03ce13f7SAndroid Build Coastguard Worker CfgVector<size_t> LocalsSize(Func->getNumNodes());
872*03ce13f7SAndroid Build Coastguard Worker const bool SimpleCoalescing = !callsReturnsTwice();
873*03ce13f7SAndroid Build Coastguard Worker
874*03ce13f7SAndroid Build Coastguard Worker for (Variable *Var : SortedSpilledVariables) {
875*03ce13f7SAndroid Build Coastguard Worker size_t Increment = typeWidthInBytesOnStack(Var->getType());
876*03ce13f7SAndroid Build Coastguard Worker if (SimpleCoalescing && VMetadata->isTracked(Var)) {
877*03ce13f7SAndroid Build Coastguard Worker if (VMetadata->isMultiBlock(Var)) {
878*03ce13f7SAndroid Build Coastguard Worker GlobalsSpaceUsed += Increment;
879*03ce13f7SAndroid Build Coastguard Worker NextStackOffset = GlobalsSpaceUsed;
880*03ce13f7SAndroid Build Coastguard Worker } else {
881*03ce13f7SAndroid Build Coastguard Worker SizeT NodeIndex = VMetadata->getLocalUseNode(Var)->getIndex();
882*03ce13f7SAndroid Build Coastguard Worker LocalsSize[NodeIndex] += Increment;
883*03ce13f7SAndroid Build Coastguard Worker NextStackOffset = SpillAreaPaddingBytes +
884*03ce13f7SAndroid Build Coastguard Worker GlobalsAndSubsequentPaddingSize +
885*03ce13f7SAndroid Build Coastguard Worker LocalsSize[NodeIndex];
886*03ce13f7SAndroid Build Coastguard Worker }
887*03ce13f7SAndroid Build Coastguard Worker } else {
888*03ce13f7SAndroid Build Coastguard Worker NextStackOffset += Increment;
889*03ce13f7SAndroid Build Coastguard Worker }
890*03ce13f7SAndroid Build Coastguard Worker if (UsesFramePointer)
891*03ce13f7SAndroid Build Coastguard Worker Var->setStackOffset(-NextStackOffset);
892*03ce13f7SAndroid Build Coastguard Worker else
893*03ce13f7SAndroid Build Coastguard Worker Var->setStackOffset(SpillAreaSizeBytes - NextStackOffset);
894*03ce13f7SAndroid Build Coastguard Worker }
895*03ce13f7SAndroid Build Coastguard Worker }
896*03ce13f7SAndroid Build Coastguard Worker
makeHelperCall(RuntimeHelper FuncID,Variable * Dest,SizeT MaxSrcs)897*03ce13f7SAndroid Build Coastguard Worker InstCall *TargetLowering::makeHelperCall(RuntimeHelper FuncID, Variable *Dest,
898*03ce13f7SAndroid Build Coastguard Worker SizeT MaxSrcs) {
899*03ce13f7SAndroid Build Coastguard Worker constexpr bool HasTailCall = false;
900*03ce13f7SAndroid Build Coastguard Worker Constant *CallTarget = Ctx->getRuntimeHelperFunc(FuncID);
901*03ce13f7SAndroid Build Coastguard Worker InstCall *Call =
902*03ce13f7SAndroid Build Coastguard Worker InstCall::create(Func, MaxSrcs, Dest, CallTarget, HasTailCall);
903*03ce13f7SAndroid Build Coastguard Worker return Call;
904*03ce13f7SAndroid Build Coastguard Worker }
905*03ce13f7SAndroid Build Coastguard Worker
shouldOptimizeMemIntrins()906*03ce13f7SAndroid Build Coastguard Worker bool TargetLowering::shouldOptimizeMemIntrins() {
907*03ce13f7SAndroid Build Coastguard Worker return Func->getOptLevel() >= Opt_1 || getFlags().getForceMemIntrinOpt();
908*03ce13f7SAndroid Build Coastguard Worker }
909*03ce13f7SAndroid Build Coastguard Worker
scalarizeArithmetic(InstArithmetic::OpKind Kind,Variable * Dest,Operand * Src0,Operand * Src1)910*03ce13f7SAndroid Build Coastguard Worker void TargetLowering::scalarizeArithmetic(InstArithmetic::OpKind Kind,
911*03ce13f7SAndroid Build Coastguard Worker Variable *Dest, Operand *Src0,
912*03ce13f7SAndroid Build Coastguard Worker Operand *Src1) {
913*03ce13f7SAndroid Build Coastguard Worker scalarizeInstruction(
914*03ce13f7SAndroid Build Coastguard Worker Dest,
915*03ce13f7SAndroid Build Coastguard Worker [this, Kind](Variable *Dest, Operand *Src0, Operand *Src1) {
916*03ce13f7SAndroid Build Coastguard Worker return Context.insert<InstArithmetic>(Kind, Dest, Src0, Src1);
917*03ce13f7SAndroid Build Coastguard Worker },
918*03ce13f7SAndroid Build Coastguard Worker Src0, Src1);
919*03ce13f7SAndroid Build Coastguard Worker }
920*03ce13f7SAndroid Build Coastguard Worker
emitWithoutPrefix(const ConstantRelocatable * C,const char * Suffix) const921*03ce13f7SAndroid Build Coastguard Worker void TargetLowering::emitWithoutPrefix(const ConstantRelocatable *C,
922*03ce13f7SAndroid Build Coastguard Worker const char *Suffix) const {
923*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
924*03ce13f7SAndroid Build Coastguard Worker return;
925*03ce13f7SAndroid Build Coastguard Worker Ostream &Str = Ctx->getStrEmit();
926*03ce13f7SAndroid Build Coastguard Worker const std::string &EmitStr = C->getEmitString();
927*03ce13f7SAndroid Build Coastguard Worker if (!EmitStr.empty()) {
928*03ce13f7SAndroid Build Coastguard Worker // C has a custom emit string, so we use it instead of the canonical
929*03ce13f7SAndroid Build Coastguard Worker // Name + Offset form.
930*03ce13f7SAndroid Build Coastguard Worker Str << EmitStr;
931*03ce13f7SAndroid Build Coastguard Worker return;
932*03ce13f7SAndroid Build Coastguard Worker }
933*03ce13f7SAndroid Build Coastguard Worker Str << C->getName() << Suffix;
934*03ce13f7SAndroid Build Coastguard Worker RelocOffsetT Offset = C->getOffset();
935*03ce13f7SAndroid Build Coastguard Worker if (Offset) {
936*03ce13f7SAndroid Build Coastguard Worker if (Offset > 0)
937*03ce13f7SAndroid Build Coastguard Worker Str << "+";
938*03ce13f7SAndroid Build Coastguard Worker Str << Offset;
939*03ce13f7SAndroid Build Coastguard Worker }
940*03ce13f7SAndroid Build Coastguard Worker }
941*03ce13f7SAndroid Build Coastguard Worker
942*03ce13f7SAndroid Build Coastguard Worker std::unique_ptr<TargetDataLowering>
createLowering(GlobalContext * Ctx)943*03ce13f7SAndroid Build Coastguard Worker TargetDataLowering::createLowering(GlobalContext *Ctx) {
944*03ce13f7SAndroid Build Coastguard Worker TargetArch Target = getFlags().getTargetArch();
945*03ce13f7SAndroid Build Coastguard Worker switch (Target) {
946*03ce13f7SAndroid Build Coastguard Worker default:
947*03ce13f7SAndroid Build Coastguard Worker badTargetFatalError(Target);
948*03ce13f7SAndroid Build Coastguard Worker #define SUBZERO_TARGET(X) \
949*03ce13f7SAndroid Build Coastguard Worker case TARGET_LOWERING_CLASS_FOR(X): \
950*03ce13f7SAndroid Build Coastguard Worker return ::X::createTargetDataLowering(Ctx);
951*03ce13f7SAndroid Build Coastguard Worker #include "SZTargets.def"
952*03ce13f7SAndroid Build Coastguard Worker #undef SUBZERO_TARGET
953*03ce13f7SAndroid Build Coastguard Worker }
954*03ce13f7SAndroid Build Coastguard Worker }
955*03ce13f7SAndroid Build Coastguard Worker
956*03ce13f7SAndroid Build Coastguard Worker TargetDataLowering::~TargetDataLowering() = default;
957*03ce13f7SAndroid Build Coastguard Worker
958*03ce13f7SAndroid Build Coastguard Worker namespace {
959*03ce13f7SAndroid Build Coastguard Worker
960*03ce13f7SAndroid Build Coastguard Worker // dataSectionSuffix decides whether to use SectionSuffix or VarName as data
961*03ce13f7SAndroid Build Coastguard Worker // section suffix. Essentially, when using separate data sections for globals
962*03ce13f7SAndroid Build Coastguard Worker // SectionSuffix is not necessary.
dataSectionSuffix(const std::string & SectionSuffix,const std::string & VarName,const bool DataSections)963*03ce13f7SAndroid Build Coastguard Worker std::string dataSectionSuffix(const std::string &SectionSuffix,
964*03ce13f7SAndroid Build Coastguard Worker const std::string &VarName,
965*03ce13f7SAndroid Build Coastguard Worker const bool DataSections) {
966*03ce13f7SAndroid Build Coastguard Worker if (SectionSuffix.empty() && !DataSections) {
967*03ce13f7SAndroid Build Coastguard Worker return "";
968*03ce13f7SAndroid Build Coastguard Worker }
969*03ce13f7SAndroid Build Coastguard Worker
970*03ce13f7SAndroid Build Coastguard Worker if (DataSections) {
971*03ce13f7SAndroid Build Coastguard Worker // With data sections we don't need to use the SectionSuffix.
972*03ce13f7SAndroid Build Coastguard Worker return "." + VarName;
973*03ce13f7SAndroid Build Coastguard Worker }
974*03ce13f7SAndroid Build Coastguard Worker
975*03ce13f7SAndroid Build Coastguard Worker assert(!SectionSuffix.empty());
976*03ce13f7SAndroid Build Coastguard Worker return "." + SectionSuffix;
977*03ce13f7SAndroid Build Coastguard Worker }
978*03ce13f7SAndroid Build Coastguard Worker
979*03ce13f7SAndroid Build Coastguard Worker } // end of anonymous namespace
980*03ce13f7SAndroid Build Coastguard Worker
emitGlobal(const VariableDeclaration & Var,const std::string & SectionSuffix)981*03ce13f7SAndroid Build Coastguard Worker void TargetDataLowering::emitGlobal(const VariableDeclaration &Var,
982*03ce13f7SAndroid Build Coastguard Worker const std::string &SectionSuffix) {
983*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
984*03ce13f7SAndroid Build Coastguard Worker return;
985*03ce13f7SAndroid Build Coastguard Worker
986*03ce13f7SAndroid Build Coastguard Worker // If external and not initialized, this must be a cross test. Don't generate
987*03ce13f7SAndroid Build Coastguard Worker // a declaration for such cases.
988*03ce13f7SAndroid Build Coastguard Worker const bool IsExternal = Var.isExternal() || getFlags().getDisableInternal();
989*03ce13f7SAndroid Build Coastguard Worker if (IsExternal && !Var.hasInitializer())
990*03ce13f7SAndroid Build Coastguard Worker return;
991*03ce13f7SAndroid Build Coastguard Worker
992*03ce13f7SAndroid Build Coastguard Worker Ostream &Str = Ctx->getStrEmit();
993*03ce13f7SAndroid Build Coastguard Worker const bool HasNonzeroInitializer = Var.hasNonzeroInitializer();
994*03ce13f7SAndroid Build Coastguard Worker const bool IsConstant = Var.getIsConstant();
995*03ce13f7SAndroid Build Coastguard Worker const SizeT Size = Var.getNumBytes();
996*03ce13f7SAndroid Build Coastguard Worker const std::string Name = Var.getName().toString();
997*03ce13f7SAndroid Build Coastguard Worker
998*03ce13f7SAndroid Build Coastguard Worker Str << "\t.type\t" << Name << ",%object\n";
999*03ce13f7SAndroid Build Coastguard Worker
1000*03ce13f7SAndroid Build Coastguard Worker const bool UseDataSections = getFlags().getDataSections();
1001*03ce13f7SAndroid Build Coastguard Worker const std::string Suffix =
1002*03ce13f7SAndroid Build Coastguard Worker dataSectionSuffix(SectionSuffix, Name, UseDataSections);
1003*03ce13f7SAndroid Build Coastguard Worker if (IsConstant)
1004*03ce13f7SAndroid Build Coastguard Worker Str << "\t.section\t.rodata" << Suffix << ",\"a\",%progbits\n";
1005*03ce13f7SAndroid Build Coastguard Worker else if (HasNonzeroInitializer)
1006*03ce13f7SAndroid Build Coastguard Worker Str << "\t.section\t.data" << Suffix << ",\"aw\",%progbits\n";
1007*03ce13f7SAndroid Build Coastguard Worker else
1008*03ce13f7SAndroid Build Coastguard Worker Str << "\t.section\t.bss" << Suffix << ",\"aw\",%nobits\n";
1009*03ce13f7SAndroid Build Coastguard Worker
1010*03ce13f7SAndroid Build Coastguard Worker if (IsExternal)
1011*03ce13f7SAndroid Build Coastguard Worker Str << "\t.globl\t" << Name << "\n";
1012*03ce13f7SAndroid Build Coastguard Worker
1013*03ce13f7SAndroid Build Coastguard Worker const uint32_t Align = Var.getAlignment();
1014*03ce13f7SAndroid Build Coastguard Worker if (Align > 1) {
1015*03ce13f7SAndroid Build Coastguard Worker assert(llvm::isPowerOf2_32(Align));
1016*03ce13f7SAndroid Build Coastguard Worker // Use the .p2align directive, since the .align N directive can either
1017*03ce13f7SAndroid Build Coastguard Worker // interpret N as bytes, or power of 2 bytes, depending on the target.
1018*03ce13f7SAndroid Build Coastguard Worker Str << "\t.p2align\t" << llvm::Log2_32(Align) << "\n";
1019*03ce13f7SAndroid Build Coastguard Worker }
1020*03ce13f7SAndroid Build Coastguard Worker
1021*03ce13f7SAndroid Build Coastguard Worker Str << Name << ":\n";
1022*03ce13f7SAndroid Build Coastguard Worker
1023*03ce13f7SAndroid Build Coastguard Worker if (HasNonzeroInitializer) {
1024*03ce13f7SAndroid Build Coastguard Worker for (const auto *Init : Var.getInitializers()) {
1025*03ce13f7SAndroid Build Coastguard Worker switch (Init->getKind()) {
1026*03ce13f7SAndroid Build Coastguard Worker case VariableDeclaration::Initializer::DataInitializerKind: {
1027*03ce13f7SAndroid Build Coastguard Worker const auto &Data =
1028*03ce13f7SAndroid Build Coastguard Worker llvm::cast<VariableDeclaration::DataInitializer>(Init)
1029*03ce13f7SAndroid Build Coastguard Worker ->getContents();
1030*03ce13f7SAndroid Build Coastguard Worker for (SizeT i = 0; i < Init->getNumBytes(); ++i) {
1031*03ce13f7SAndroid Build Coastguard Worker Str << "\t.byte\t" << (((unsigned)Data[i]) & 0xff) << "\n";
1032*03ce13f7SAndroid Build Coastguard Worker }
1033*03ce13f7SAndroid Build Coastguard Worker break;
1034*03ce13f7SAndroid Build Coastguard Worker }
1035*03ce13f7SAndroid Build Coastguard Worker case VariableDeclaration::Initializer::ZeroInitializerKind:
1036*03ce13f7SAndroid Build Coastguard Worker Str << "\t.zero\t" << Init->getNumBytes() << "\n";
1037*03ce13f7SAndroid Build Coastguard Worker break;
1038*03ce13f7SAndroid Build Coastguard Worker case VariableDeclaration::Initializer::RelocInitializerKind: {
1039*03ce13f7SAndroid Build Coastguard Worker const auto *Reloc =
1040*03ce13f7SAndroid Build Coastguard Worker llvm::cast<VariableDeclaration::RelocInitializer>(Init);
1041*03ce13f7SAndroid Build Coastguard Worker Str << "\t" << getEmit32Directive() << "\t";
1042*03ce13f7SAndroid Build Coastguard Worker Str << Reloc->getDeclaration()->getName();
1043*03ce13f7SAndroid Build Coastguard Worker if (Reloc->hasFixup()) {
1044*03ce13f7SAndroid Build Coastguard Worker // TODO(jpp): this is ARM32 specific.
1045*03ce13f7SAndroid Build Coastguard Worker Str << "(GOTOFF)";
1046*03ce13f7SAndroid Build Coastguard Worker }
1047*03ce13f7SAndroid Build Coastguard Worker if (RelocOffsetT Offset = Reloc->getOffset()) {
1048*03ce13f7SAndroid Build Coastguard Worker if (Offset >= 0 || (Offset == INT32_MIN))
1049*03ce13f7SAndroid Build Coastguard Worker Str << " + " << Offset;
1050*03ce13f7SAndroid Build Coastguard Worker else
1051*03ce13f7SAndroid Build Coastguard Worker Str << " - " << -Offset;
1052*03ce13f7SAndroid Build Coastguard Worker }
1053*03ce13f7SAndroid Build Coastguard Worker Str << "\n";
1054*03ce13f7SAndroid Build Coastguard Worker break;
1055*03ce13f7SAndroid Build Coastguard Worker }
1056*03ce13f7SAndroid Build Coastguard Worker }
1057*03ce13f7SAndroid Build Coastguard Worker }
1058*03ce13f7SAndroid Build Coastguard Worker } else {
1059*03ce13f7SAndroid Build Coastguard Worker // NOTE: for non-constant zero initializers, this is BSS (no bits), so an
1060*03ce13f7SAndroid Build Coastguard Worker // ELF writer would not write to the file, and only track virtual offsets,
1061*03ce13f7SAndroid Build Coastguard Worker // but the .s writer still needs this .zero and cannot simply use the .size
1062*03ce13f7SAndroid Build Coastguard Worker // to advance offsets.
1063*03ce13f7SAndroid Build Coastguard Worker Str << "\t.zero\t" << Size << "\n";
1064*03ce13f7SAndroid Build Coastguard Worker }
1065*03ce13f7SAndroid Build Coastguard Worker
1066*03ce13f7SAndroid Build Coastguard Worker Str << "\t.size\t" << Name << ", " << Size << "\n";
1067*03ce13f7SAndroid Build Coastguard Worker }
1068*03ce13f7SAndroid Build Coastguard Worker
1069*03ce13f7SAndroid Build Coastguard Worker std::unique_ptr<TargetHeaderLowering>
createLowering(GlobalContext * Ctx)1070*03ce13f7SAndroid Build Coastguard Worker TargetHeaderLowering::createLowering(GlobalContext *Ctx) {
1071*03ce13f7SAndroid Build Coastguard Worker TargetArch Target = getFlags().getTargetArch();
1072*03ce13f7SAndroid Build Coastguard Worker switch (Target) {
1073*03ce13f7SAndroid Build Coastguard Worker default:
1074*03ce13f7SAndroid Build Coastguard Worker badTargetFatalError(Target);
1075*03ce13f7SAndroid Build Coastguard Worker #define SUBZERO_TARGET(X) \
1076*03ce13f7SAndroid Build Coastguard Worker case TARGET_LOWERING_CLASS_FOR(X): \
1077*03ce13f7SAndroid Build Coastguard Worker return ::X::createTargetHeaderLowering(Ctx);
1078*03ce13f7SAndroid Build Coastguard Worker #include "SZTargets.def"
1079*03ce13f7SAndroid Build Coastguard Worker #undef SUBZERO_TARGET
1080*03ce13f7SAndroid Build Coastguard Worker }
1081*03ce13f7SAndroid Build Coastguard Worker }
1082*03ce13f7SAndroid Build Coastguard Worker
1083*03ce13f7SAndroid Build Coastguard Worker TargetHeaderLowering::~TargetHeaderLowering() = default;
1084*03ce13f7SAndroid Build Coastguard Worker
1085*03ce13f7SAndroid Build Coastguard Worker } // end of namespace Ice
1086