xref: /aosp_15_r20/external/swiftshader/third_party/subzero/src/IceTargetLowering.cpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
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