blob: 3d8537d5323e55f104645962716627321be34ffd [file] [log] [blame]
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001//===- subzero/src/IceTargetLowering.cpp - Basic lowering implementation --===//
2//
3// The Subzero Code Generator
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
Andrew Scull9612d322015-07-06 14:53:25 -07009///
10/// \file
Jim Stichnoth92a6e5b2015-12-02 16:52:44 -080011/// \brief Implements the skeleton of the TargetLowering class.
12///
13/// Specifically this invokes the appropriate lowering method for a given
14/// instruction kind and driving global register allocation. It also implements
15/// the non-deleted instruction iteration in LoweringContext.
Andrew Scull9612d322015-07-06 14:53:25 -070016///
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070017//===----------------------------------------------------------------------===//
18
John Porto67f8de92015-06-25 10:14:17 -070019#include "IceTargetLowering.h"
20
John Porto36d6aa62016-02-26 07:19:59 -080021#include "IceBitVector.h"
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070022#include "IceCfg.h" // setError()
23#include "IceCfgNode.h"
John Porto53611e22015-12-30 07:30:10 -080024#include "IceGlobalContext.h"
Jan Voung58eea4d2015-06-15 15:11:56 -070025#include "IceGlobalInits.h"
John Portoec3f5652015-08-31 15:07:09 -070026#include "IceInstVarIter.h"
Manasij Mukherjee7cd926d2016-08-04 12:33:23 -070027#include "IceLiveness.h"
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070028#include "IceOperand.h"
Jim Stichnothd97c7df2014-06-04 11:57:08 -070029#include "IceRegAlloc.h"
John Porto53611e22015-12-30 07:30:10 -080030
John Portoc5bc5cb2016-03-21 11:18:02 -070031#include <string>
32#include <vector>
33
Jim Stichnoth999a22f2016-03-12 10:22:53 -080034#define TARGET_LOWERING_CLASS_FOR(t) Target_##t
35
John Porto53611e22015-12-30 07:30:10 -080036// We prevent target-specific implementation details from leaking outside their
37// implementations by forbidding #include of target-specific header files
38// anywhere outside their own files. To create target-specific objects
39// (TargetLowering, TargetDataLowering, and TargetHeaderLowering) we use the
40// following named constructors. For reference, each target Foo needs to
41// implement the following named constructors and initializer:
42//
43// namespace Foo {
44// unique_ptr<Ice::TargetLowering> createTargetLowering(Ice::Cfg *);
45// unique_ptr<Ice::TargetDataLowering>
46// createTargetDataLowering(Ice::GlobalContext*);
47// unique_ptr<Ice::TargetHeaderLowering>
48// createTargetHeaderLowering(Ice::GlobalContext *);
Karl Schimpf5403f5d2016-01-15 11:07:46 -080049// void staticInit(::Ice::GlobalContext *);
John Porto53611e22015-12-30 07:30:10 -080050// }
51#define SUBZERO_TARGET(X) \
52 namespace X { \
53 std::unique_ptr<::Ice::TargetLowering> \
54 createTargetLowering(::Ice::Cfg *Func); \
55 std::unique_ptr<::Ice::TargetDataLowering> \
56 createTargetDataLowering(::Ice::GlobalContext *Ctx); \
57 std::unique_ptr<::Ice::TargetHeaderLowering> \
58 createTargetHeaderLowering(::Ice::GlobalContext *Ctx); \
Karl Schimpf5403f5d2016-01-15 11:07:46 -080059 void staticInit(::Ice::GlobalContext *Ctx); \
Jim Stichnoth467ffe52016-03-29 15:01:06 -070060 bool shouldBePooled(const ::Ice::Constant *C); \
Nicolas Capens32f9cce2016-10-19 01:24:27 -040061 ::Ice::Type getPointerType(); \
John Porto53611e22015-12-30 07:30:10 -080062 } // end of namespace X
Jim Stichnoth999a22f2016-03-12 10:22:53 -080063#include "SZTargets.def"
John Porto53611e22015-12-30 07:30:10 -080064#undef SUBZERO_TARGET
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070065
66namespace Ice {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070067void LoweringContext::init(CfgNode *N) {
68 Node = N;
Jim Stichnoth336f6c42014-10-30 15:01:31 -070069 End = getNode()->getInsts().end();
70 rewind();
71 advanceForward(Next);
72}
73
74void LoweringContext::rewind() {
Jan Vounge6e497d2014-07-30 10:06:03 -070075 Begin = getNode()->getInsts().begin();
76 Cur = Begin;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070077 skipDeleted(Cur);
78 Next = Cur;
Jim Stichnoth318f4cd2015-10-01 21:02:37 -070079 availabilityReset();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070080}
81
Jim Stichnoth8cfeb692016-02-05 09:50:02 -080082void LoweringContext::insert(Inst *Instr) {
83 getNode()->getInsts().insert(Next, Instr);
84 LastInserted = Instr;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070085}
86
Jan Voungc820ddf2014-07-29 14:38:51 -070087void LoweringContext::skipDeleted(InstList::iterator &I) const {
Jim Stichnoth607e9f02014-11-06 13:32:05 -080088 while (I != End && I->isDeleted())
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070089 ++I;
90}
91
Jan Vounge6e497d2014-07-30 10:06:03 -070092void LoweringContext::advanceForward(InstList::iterator &I) const {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070093 if (I != End) {
94 ++I;
95 skipDeleted(I);
96 }
97}
98
Jan Vounge6e497d2014-07-30 10:06:03 -070099Inst *LoweringContext::getLastInserted() const {
Jim Stichnoth98712a32014-10-24 10:59:02 -0700100 assert(LastInserted);
101 return LastInserted;
Jan Vounge6e497d2014-07-30 10:06:03 -0700102}
103
Jim Stichnoth318f4cd2015-10-01 21:02:37 -0700104void LoweringContext::availabilityReset() {
105 LastDest = nullptr;
106 LastSrc = nullptr;
107}
108
109void LoweringContext::availabilityUpdate() {
110 availabilityReset();
111 Inst *Instr = LastInserted;
112 if (Instr == nullptr)
113 return;
Jim Stichnoth28b71be2015-10-12 15:24:46 -0700114 if (!Instr->isVarAssign())
Jim Stichnoth318f4cd2015-10-01 21:02:37 -0700115 return;
Jim Stichnoth28b71be2015-10-12 15:24:46 -0700116 // Since isVarAssign() is true, the source operand must be a Variable.
117 LastDest = Instr->getDest();
118 LastSrc = llvm::cast<Variable>(Instr->getSrc(0));
Jim Stichnoth318f4cd2015-10-01 21:02:37 -0700119}
120
121Variable *LoweringContext::availabilityGet(Operand *Src) const {
122 assert(Src);
123 if (Src == LastDest)
124 return LastSrc;
125 return nullptr;
126}
127
Karl Schimpf5403f5d2016-01-15 11:07:46 -0800128namespace {
129
John Portoe82b5602016-02-24 15:58:55 -0800130void printRegisterSet(Ostream &Str, const SmallBitVector &Bitset,
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700131 std::function<std::string(RegNumT)> getRegName,
132 const std::string &LineIndentString) {
Karl Schimpf5403f5d2016-01-15 11:07:46 -0800133 constexpr size_t RegistersPerLine = 16;
134 size_t Count = 0;
Jim Stichnoth8aa39662016-02-10 11:20:30 -0800135 for (RegNumT RegNum : RegNumBVIter(Bitset)) {
Karl Schimpf5403f5d2016-01-15 11:07:46 -0800136 if (Count == 0) {
137 Str << LineIndentString;
138 } else {
139 Str << ",";
140 }
141 if (Count > 0 && Count % RegistersPerLine == 0)
142 Str << "\n" << LineIndentString;
143 ++Count;
Jim Stichnoth8aa39662016-02-10 11:20:30 -0800144 Str << getRegName(RegNum);
Karl Schimpf5403f5d2016-01-15 11:07:46 -0800145 }
146 if (Count)
147 Str << "\n";
148}
149
Jim Stichnoth2544d4d2016-01-22 13:07:46 -0800150// Splits "<class>:<reg>" into "<class>" plus "<reg>". If there is no <class>
151// component, the result is "" plus "<reg>".
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700152void splitToClassAndName(const std::string &RegName, std::string *SplitRegClass,
153 std::string *SplitRegName) {
Jim Stichnoth2544d4d2016-01-22 13:07:46 -0800154 constexpr const char Separator[] = ":";
155 constexpr size_t SeparatorWidth = llvm::array_lengthof(Separator) - 1;
156 size_t Pos = RegName.find(Separator);
157 if (Pos == std::string::npos) {
158 *SplitRegClass = "";
159 *SplitRegName = RegName;
160 } else {
161 *SplitRegClass = RegName.substr(0, Pos);
162 *SplitRegName = RegName.substr(Pos + SeparatorWidth);
163 }
164}
165
Jim Stichnoth816fd682016-02-16 05:47:32 -0800166LLVM_ATTRIBUTE_NORETURN void badTargetFatalError(TargetArch Target) {
167 llvm::report_fatal_error("Unsupported target: " +
168 std::string(targetArchString(Target)));
169}
170
Karl Schimpf5403f5d2016-01-15 11:07:46 -0800171} // end of anonymous namespace
172
173void TargetLowering::filterTypeToRegisterSet(
John Portoe82b5602016-02-24 15:58:55 -0800174 GlobalContext *Ctx, int32_t NumRegs, SmallBitVector TypeToRegisterSet[],
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700175 size_t TypeToRegisterSetSize,
176 std::function<std::string(RegNumT)> getRegName,
177 std::function<const char *(RegClass)> getRegClassName) {
John Portoe82b5602016-02-24 15:58:55 -0800178 std::vector<SmallBitVector> UseSet(TypeToRegisterSetSize,
179 SmallBitVector(NumRegs));
180 std::vector<SmallBitVector> ExcludeSet(TypeToRegisterSetSize,
181 SmallBitVector(NumRegs));
Karl Schimpf5403f5d2016-01-15 11:07:46 -0800182
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700183 std::unordered_map<std::string, RegNumT> RegNameToIndex;
Jim Stichnoth8aa39662016-02-10 11:20:30 -0800184 for (int32_t RegIndex = 0; RegIndex < NumRegs; ++RegIndex) {
185 const auto RegNum = RegNumT::fromInt(RegIndex);
186 RegNameToIndex[getRegName(RegNum)] = RegNum;
187 }
Karl Schimpf5403f5d2016-01-15 11:07:46 -0800188
John Portoc5bc5cb2016-03-21 11:18:02 -0700189 std::vector<std::string> BadRegNames;
Karl Schimpf5403f5d2016-01-15 11:07:46 -0800190
Jim Stichnoth2544d4d2016-01-22 13:07:46 -0800191 // The processRegList function iterates across the RegNames vector. Each
192 // entry in the vector is a string of the form "<reg>" or "<class>:<reg>".
193 // The register class and register number are computed, and the corresponding
194 // bit is set in RegSet[][]. If "<class>:" is missing, then the bit is set
195 // for all classes.
John Portoc5bc5cb2016-03-21 11:18:02 -0700196 auto processRegList = [&](const std::vector<std::string> &RegNames,
John Portoe82b5602016-02-24 15:58:55 -0800197 std::vector<SmallBitVector> &RegSet) {
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700198 for (const std::string &RegClassAndName : RegNames) {
199 std::string RClass;
200 std::string RName;
Jim Stichnoth2544d4d2016-01-22 13:07:46 -0800201 splitToClassAndName(RegClassAndName, &RClass, &RName);
202 if (!RegNameToIndex.count(RName)) {
203 BadRegNames.push_back(RName);
204 continue;
205 }
206 const int32_t RegIndex = RegNameToIndex.at(RName);
207 for (SizeT TypeIndex = 0; TypeIndex < TypeToRegisterSetSize;
208 ++TypeIndex) {
209 if (RClass.empty() ||
210 RClass == getRegClassName(static_cast<RegClass>(TypeIndex))) {
211 RegSet[TypeIndex][RegIndex] = TypeToRegisterSet[TypeIndex][RegIndex];
212 }
213 }
Karl Schimpf5403f5d2016-01-15 11:07:46 -0800214 }
Jim Stichnoth2544d4d2016-01-22 13:07:46 -0800215 };
216
Karl Schimpfd4699942016-04-02 09:55:31 -0700217 processRegList(getFlags().getUseRestrictedRegisters(), UseSet);
218 processRegList(getFlags().getExcludedRegisters(), ExcludeSet);
Karl Schimpf5403f5d2016-01-15 11:07:46 -0800219
220 if (!BadRegNames.empty()) {
221 std::string Buffer;
222 llvm::raw_string_ostream StrBuf(Buffer);
223 StrBuf << "Unrecognized use/exclude registers:";
224 for (const auto &RegName : BadRegNames)
225 StrBuf << " " << RegName;
226 llvm::report_fatal_error(StrBuf.str());
227 }
228
229 // Apply filters.
230 for (size_t TypeIndex = 0; TypeIndex < TypeToRegisterSetSize; ++TypeIndex) {
John Portoe82b5602016-02-24 15:58:55 -0800231 SmallBitVector *TypeBitSet = &TypeToRegisterSet[TypeIndex];
232 SmallBitVector *UseBitSet = &UseSet[TypeIndex];
233 SmallBitVector *ExcludeBitSet = &ExcludeSet[TypeIndex];
Karl Schimpf5403f5d2016-01-15 11:07:46 -0800234 if (UseBitSet->any())
235 *TypeBitSet = *UseBitSet;
Jim Stichnoth2544d4d2016-01-22 13:07:46 -0800236 (*TypeBitSet).reset(*ExcludeBitSet);
Karl Schimpf5403f5d2016-01-15 11:07:46 -0800237 }
238
239 // Display filtered register sets, if requested.
240 if (BuildDefs::dump() && NumRegs &&
Karl Schimpfd4699942016-04-02 09:55:31 -0700241 (getFlags().getVerbose() & IceV_AvailableRegs)) {
Karl Schimpf5403f5d2016-01-15 11:07:46 -0800242 Ostream &Str = Ctx->getStrDump();
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700243 const std::string Indent = " ";
244 const std::string IndentTwice = Indent + Indent;
Karl Schimpf5403f5d2016-01-15 11:07:46 -0800245 Str << "Registers available for register allocation:\n";
246 for (size_t TypeIndex = 0; TypeIndex < TypeToRegisterSetSize; ++TypeIndex) {
Jim Stichnoth2544d4d2016-01-22 13:07:46 -0800247 Str << Indent << getRegClassName(static_cast<RegClass>(TypeIndex))
248 << ":\n";
Karl Schimpf5403f5d2016-01-15 11:07:46 -0800249 printRegisterSet(Str, TypeToRegisterSet[TypeIndex], getRegName,
250 IndentTwice);
251 }
252 Str << "\n";
253 }
254}
255
John Porto53611e22015-12-30 07:30:10 -0800256std::unique_ptr<TargetLowering>
257TargetLowering::createLowering(TargetArch Target, Cfg *Func) {
258 switch (Target) {
259 default:
Jim Stichnoth816fd682016-02-16 05:47:32 -0800260 badTargetFatalError(Target);
Jan Voungb36ad9b2015-04-21 17:01:49 -0700261#define SUBZERO_TARGET(X) \
Jim Stichnoth999a22f2016-03-12 10:22:53 -0800262 case TARGET_LOWERING_CLASS_FOR(X): \
John Porto53611e22015-12-30 07:30:10 -0800263 return ::X::createTargetLowering(Func);
Jim Stichnoth999a22f2016-03-12 10:22:53 -0800264#include "SZTargets.def"
John Porto53611e22015-12-30 07:30:10 -0800265#undef SUBZERO_TARGET
266 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700267}
268
Karl Schimpf5403f5d2016-01-15 11:07:46 -0800269void TargetLowering::staticInit(GlobalContext *Ctx) {
Karl Schimpfd4699942016-04-02 09:55:31 -0700270 const TargetArch Target = getFlags().getTargetArch();
Jim Stichnoth94844f12015-11-04 16:06:16 -0800271 // Call the specified target's static initializer.
272 switch (Target) {
273 default:
Jim Stichnoth816fd682016-02-16 05:47:32 -0800274 badTargetFatalError(Target);
Jim Stichnoth94844f12015-11-04 16:06:16 -0800275#define SUBZERO_TARGET(X) \
Jim Stichnoth999a22f2016-03-12 10:22:53 -0800276 case TARGET_LOWERING_CLASS_FOR(X): { \
Jim Stichnoth94844f12015-11-04 16:06:16 -0800277 static bool InitGuard##X = false; \
John Porto53611e22015-12-30 07:30:10 -0800278 if (InitGuard##X) { \
Jim Stichnoth94844f12015-11-04 16:06:16 -0800279 return; \
John Porto53611e22015-12-30 07:30:10 -0800280 } \
Jim Stichnoth94844f12015-11-04 16:06:16 -0800281 InitGuard##X = true; \
Karl Schimpf5403f5d2016-01-15 11:07:46 -0800282 ::X::staticInit(Ctx); \
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800283 } break;
Jim Stichnoth999a22f2016-03-12 10:22:53 -0800284#include "SZTargets.def"
John Porto53611e22015-12-30 07:30:10 -0800285#undef SUBZERO_TARGET
Jim Stichnoth94844f12015-11-04 16:06:16 -0800286 }
287}
288
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700289bool TargetLowering::shouldBePooled(const Constant *C) {
Karl Schimpfd4699942016-04-02 09:55:31 -0700290 const TargetArch Target = getFlags().getTargetArch();
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700291 switch (Target) {
292 default:
293 return false;
294#define SUBZERO_TARGET(X) \
295 case TARGET_LOWERING_CLASS_FOR(X): \
296 return ::X::shouldBePooled(C);
297#include "SZTargets.def"
298#undef SUBZERO_TARGET
299 }
300}
301
Nicolas Capens32f9cce2016-10-19 01:24:27 -0400302::Ice::Type TargetLowering::getPointerType() {
303 const TargetArch Target = getFlags().getTargetArch();
304 switch (Target) {
305 default:
306 return ::Ice::IceType_void;
307#define SUBZERO_TARGET(X) \
308 case TARGET_LOWERING_CLASS_FOR(X): \
309 return ::X::getPointerType();
310#include "SZTargets.def"
311#undef SUBZERO_TARGET
312 }
313}
314
John Portoac2388c2016-01-22 07:10:56 -0800315TargetLowering::SandboxType
316TargetLowering::determineSandboxTypeFromFlags(const ClFlags &Flags) {
317 assert(!Flags.getUseSandboxing() || !Flags.getUseNonsfi());
318 if (Flags.getUseNonsfi()) {
319 return TargetLowering::ST_Nonsfi;
320 }
321 if (Flags.getUseSandboxing()) {
322 return TargetLowering::ST_NaCl;
323 }
324 return TargetLowering::ST_None;
325}
326
Jim Stichnothe6d24782014-12-19 05:42:24 -0800327TargetLowering::TargetLowering(Cfg *Func)
John Portoac2388c2016-01-22 07:10:56 -0800328 : Func(Func), Ctx(Func->getContext()),
Karl Schimpfd4699942016-04-02 09:55:31 -0700329 SandboxingType(determineSandboxTypeFromFlags(getFlags())) {}
Jim Stichnothe6d24782014-12-19 05:42:24 -0800330
John Porto3bf335f2016-01-15 11:17:55 -0800331TargetLowering::AutoBundle::AutoBundle(TargetLowering *Target,
332 InstBundleLock::Option Option)
Karl Schimpfd4699942016-04-02 09:55:31 -0700333 : Target(Target), NeedSandboxing(getFlags().getUseSandboxing()) {
John Porto3bf335f2016-01-15 11:17:55 -0800334 assert(!Target->AutoBundling);
335 Target->AutoBundling = true;
336 if (NeedSandboxing) {
337 Target->_bundle_lock(Option);
338 }
339}
340
341TargetLowering::AutoBundle::~AutoBundle() {
342 assert(Target->AutoBundling);
343 Target->AutoBundling = false;
344 if (NeedSandboxing) {
345 Target->_bundle_unlock();
346 }
347}
348
John Porto5e0a8a72015-11-20 13:50:36 -0800349void TargetLowering::genTargetHelperCalls() {
Jim Stichnothb88d8c82016-03-11 15:33:00 -0800350 TimerMarker T(TimerStack::TT_genHelpers, Func);
Eric Holkd6cf6b32016-02-17 11:09:48 -0800351 Utils::BoolFlagSaver _(GeneratingTargetHelpers, true);
John Porto5e0a8a72015-11-20 13:50:36 -0800352 for (CfgNode *Node : Func->getNodes()) {
353 Context.init(Node);
354 while (!Context.atEnd()) {
355 PostIncrLoweringContext _(Context);
Jim Stichnothf5fdd232016-05-09 12:24:36 -0700356 genTargetHelperCallFor(iteratorToInst(Context.getCur()));
John Porto5e0a8a72015-11-20 13:50:36 -0800357 }
358 }
359}
360
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700361void TargetLowering::doAddressOpt() {
Manasij Mukherjee0c704172016-07-21 12:40:24 -0700362 doAddressOptOther();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700363 if (llvm::isa<InstLoad>(*Context.getCur()))
364 doAddressOptLoad();
365 else if (llvm::isa<InstStore>(*Context.getCur()))
366 doAddressOptStore();
Nicolas Capense986b312017-01-27 00:56:42 -0800367 else if (auto *Intrinsic =
368 llvm::dyn_cast<InstIntrinsicCall>(&*Context.getCur())) {
369 if (Intrinsic->getIntrinsicInfo().ID == Intrinsics::LoadSubVector)
370 doAddressOptLoadSubVector();
371 else if (Intrinsic->getIntrinsicInfo().ID == Intrinsics::StoreSubVector)
372 doAddressOptStoreSubVector();
373 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700374 Context.advanceCur();
375 Context.advanceNext();
376}
377
Qining Luaee5fa82015-08-20 14:59:03 -0700378void TargetLowering::doNopInsertion(RandomNumberGenerator &RNG) {
Jim Stichnothf5fdd232016-05-09 12:24:36 -0700379 Inst *I = iteratorToInst(Context.getCur());
Matt Walac3302742014-08-15 16:21:56 -0700380 bool ShouldSkip = llvm::isa<InstFakeUse>(I) || llvm::isa<InstFakeDef>(I) ||
381 llvm::isa<InstFakeKill>(I) || I->isRedundantAssign() ||
382 I->isDeleted();
383 if (!ShouldSkip) {
Karl Schimpfd4699942016-04-02 09:55:31 -0700384 int Probability = getFlags().getNopProbabilityAsPercentage();
385 for (int I = 0; I < getFlags().getMaxNopsPerInstruction(); ++I) {
Qining Luaee5fa82015-08-20 14:59:03 -0700386 randomlyInsertNop(Probability / 100.0, RNG);
Matt Walac3302742014-08-15 16:21:56 -0700387 }
388 }
389}
390
Andrew Scull57e12682015-09-16 11:30:19 -0700391// Lowers a single instruction according to the information in Context, by
392// checking the Context.Cur instruction kind and calling the appropriate
393// lowering method. The lowering method should insert target instructions at
394// the Cur.Next insertion point, and should not delete the Context.Cur
395// instruction or advance Context.Cur.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700396//
Andrew Scull57e12682015-09-16 11:30:19 -0700397// The lowering method may look ahead in the instruction stream as desired, and
398// lower additional instructions in conjunction with the current one, for
399// example fusing a compare and branch. If it does, it should advance
400// Context.Cur to point to the next non-deleted instruction to process, and it
401// should delete any additional instructions it consumes.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700402void TargetLowering::lower() {
403 assert(!Context.atEnd());
Jim Stichnothf5fdd232016-05-09 12:24:36 -0700404 Inst *Instr = iteratorToInst(Context.getCur());
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800405 Instr->deleteIfDead();
406 if (!Instr->isDeleted() && !llvm::isa<InstFakeDef>(Instr) &&
407 !llvm::isa<InstFakeUse>(Instr)) {
Andrew Scull57e12682015-09-16 11:30:19 -0700408 // Mark the current instruction as deleted before lowering, otherwise the
409 // Dest variable will likely get marked as non-SSA. See
410 // Variable::setDefinition(). However, just pass-through FakeDef and
411 // FakeUse instructions that might have been inserted prior to lowering.
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800412 Instr->setDeleted();
413 switch (Instr->getKind()) {
Jim Stichnotha59ae6f2015-05-17 10:11:41 -0700414 case Inst::Alloca:
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800415 lowerAlloca(llvm::cast<InstAlloca>(Instr));
Jim Stichnotha59ae6f2015-05-17 10:11:41 -0700416 break;
417 case Inst::Arithmetic:
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800418 lowerArithmetic(llvm::cast<InstArithmetic>(Instr));
Jim Stichnotha59ae6f2015-05-17 10:11:41 -0700419 break;
420 case Inst::Assign:
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800421 lowerAssign(llvm::cast<InstAssign>(Instr));
Jim Stichnotha59ae6f2015-05-17 10:11:41 -0700422 break;
423 case Inst::Br:
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800424 lowerBr(llvm::cast<InstBr>(Instr));
Jim Stichnotha59ae6f2015-05-17 10:11:41 -0700425 break;
Eric Holk67c7c412016-04-15 13:05:37 -0700426 case Inst::Breakpoint:
427 lowerBreakpoint(llvm::cast<InstBreakpoint>(Instr));
428 break;
Jim Stichnotha59ae6f2015-05-17 10:11:41 -0700429 case Inst::Call:
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800430 lowerCall(llvm::cast<InstCall>(Instr));
Jim Stichnotha59ae6f2015-05-17 10:11:41 -0700431 break;
432 case Inst::Cast:
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800433 lowerCast(llvm::cast<InstCast>(Instr));
Jim Stichnotha59ae6f2015-05-17 10:11:41 -0700434 break;
435 case Inst::ExtractElement:
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800436 lowerExtractElement(llvm::cast<InstExtractElement>(Instr));
Jim Stichnotha59ae6f2015-05-17 10:11:41 -0700437 break;
438 case Inst::Fcmp:
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800439 lowerFcmp(llvm::cast<InstFcmp>(Instr));
Jim Stichnotha59ae6f2015-05-17 10:11:41 -0700440 break;
441 case Inst::Icmp:
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800442 lowerIcmp(llvm::cast<InstIcmp>(Instr));
Jim Stichnotha59ae6f2015-05-17 10:11:41 -0700443 break;
444 case Inst::InsertElement:
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800445 lowerInsertElement(llvm::cast<InstInsertElement>(Instr));
Jim Stichnotha59ae6f2015-05-17 10:11:41 -0700446 break;
447 case Inst::IntrinsicCall: {
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800448 auto *Call = llvm::cast<InstIntrinsicCall>(Instr);
Jim Stichnotha59ae6f2015-05-17 10:11:41 -0700449 if (Call->getIntrinsicInfo().ReturnsTwice)
450 setCallsReturnsTwice(true);
451 lowerIntrinsicCall(Call);
452 break;
453 }
454 case Inst::Load:
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800455 lowerLoad(llvm::cast<InstLoad>(Instr));
Jim Stichnotha59ae6f2015-05-17 10:11:41 -0700456 break;
457 case Inst::Phi:
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800458 lowerPhi(llvm::cast<InstPhi>(Instr));
Jim Stichnotha59ae6f2015-05-17 10:11:41 -0700459 break;
460 case Inst::Ret:
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800461 lowerRet(llvm::cast<InstRet>(Instr));
Jim Stichnotha59ae6f2015-05-17 10:11:41 -0700462 break;
463 case Inst::Select:
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800464 lowerSelect(llvm::cast<InstSelect>(Instr));
Jim Stichnotha59ae6f2015-05-17 10:11:41 -0700465 break;
John Portoa47c11c2016-04-21 05:53:42 -0700466 case Inst::ShuffleVector:
467 lowerShuffleVector(llvm::cast<InstShuffleVector>(Instr));
468 break;
Jim Stichnotha59ae6f2015-05-17 10:11:41 -0700469 case Inst::Store:
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800470 lowerStore(llvm::cast<InstStore>(Instr));
Jim Stichnotha59ae6f2015-05-17 10:11:41 -0700471 break;
472 case Inst::Switch:
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800473 lowerSwitch(llvm::cast<InstSwitch>(Instr));
Jim Stichnotha59ae6f2015-05-17 10:11:41 -0700474 break;
475 case Inst::Unreachable:
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800476 lowerUnreachable(llvm::cast<InstUnreachable>(Instr));
Jim Stichnotha59ae6f2015-05-17 10:11:41 -0700477 break;
Jim Stichnothe4f65d82015-06-17 22:16:02 -0700478 default:
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800479 lowerOther(Instr);
Jim Stichnotha59ae6f2015-05-17 10:11:41 -0700480 break;
481 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700482
Jim Stichnotha59ae6f2015-05-17 10:11:41 -0700483 postLower();
484 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700485
486 Context.advanceCur();
487 Context.advanceNext();
488}
489
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700490void TargetLowering::lowerInst(CfgNode *Node, InstList::iterator Next,
491 InstHighLevel *Instr) {
492 // TODO(stichnot): Consider modifying the design/implementation to avoid
493 // multiple init() calls when using lowerInst() to lower several instructions
494 // in the same node.
495 Context.init(Node);
496 Context.setNext(Next);
497 Context.insert(Instr);
498 --Next;
Jim Stichnothf5fdd232016-05-09 12:24:36 -0700499 assert(iteratorToInst(Next) == Instr);
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700500 Context.setCur(Next);
501 lower();
502}
503
Jim Stichnothe4f65d82015-06-17 22:16:02 -0700504void TargetLowering::lowerOther(const Inst *Instr) {
505 (void)Instr;
506 Func->setError("Can't lower unsupported instruction type");
507}
508
Andrew Scull57e12682015-09-16 11:30:19 -0700509// Drives register allocation, allowing all physical registers (except perhaps
510// for the frame pointer) to be allocated. This set of registers could
511// potentially be parameterized if we want to restrict registers e.g. for
512// performance testing.
Jim Stichnoth70d0a052014-11-14 15:53:46 -0800513void TargetLowering::regAlloc(RegAllocKind Kind) {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700514 TimerMarker T(TimerStack::TT_regAlloc, Func);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700515 LinearScan LinearScan(Func);
516 RegSetMask RegInclude = RegSet_None;
517 RegSetMask RegExclude = RegSet_None;
518 RegInclude |= RegSet_CallerSave;
519 RegInclude |= RegSet_CalleeSave;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700520 if (hasFramePointer())
521 RegExclude |= RegSet_FramePointer;
John Portoe82b5602016-02-24 15:58:55 -0800522 SmallBitVector RegMask = getRegisterSet(RegInclude, RegExclude);
Karl Schimpfd4699942016-04-02 09:55:31 -0700523 bool Repeat = (Kind == RAK_Global && getFlags().getRepeatRegAlloc());
Nicolas Capens8bd18e12017-01-20 15:21:45 -0500524 CfgSet<Variable *> EmptySet;
Jim Stichnoth4001c932015-10-09 14:33:26 -0700525 do {
Nicolas Capens8bd18e12017-01-20 15:21:45 -0500526 LinearScan.init(Kind, EmptySet);
Karl Schimpfd4699942016-04-02 09:55:31 -0700527 LinearScan.scan(RegMask, getFlags().getRandomizeRegisterAllocation());
Jim Stichnoth4001c932015-10-09 14:33:26 -0700528 if (!LinearScan.hasEvictions())
529 Repeat = false;
530 Kind = RAK_SecondChance;
531 } while (Repeat);
Jim Stichnotha1da6ff2015-11-16 15:59:39 -0800532 // TODO(stichnot): Run the register allocator one more time to do stack slot
533 // coalescing. The idea would be to initialize the Unhandled list with the
534 // set of Variables that have no register and a non-empty live range, and
535 // model an infinite number of registers. Maybe use the register aliasing
536 // mechanism to get better packing of narrower slots.
Manasij Mukherjee7cd926d2016-08-04 12:33:23 -0700537 if (getFlags().getSplitGlobalVars())
538 postRegallocSplitting(RegMask);
539}
540
541namespace {
542CfgVector<Inst *> getInstructionsInRange(CfgNode *Node, InstNumberT Start,
543 InstNumberT End) {
544 CfgVector<Inst *> Result;
545 bool Started = false;
546 auto Process = [&](InstList &Insts) {
547 for (auto &Instr : Insts) {
548 if (Instr.isDeleted()) {
549 continue;
550 }
551 if (Instr.getNumber() == Start) {
552 Started = true;
553 }
554 if (Started) {
555 Result.emplace_back(&Instr);
556 }
557 if (Instr.getNumber() == End) {
558 break;
559 }
560 }
561 };
562 Process(Node->getPhis());
563 Process(Node->getInsts());
564 // TODO(manasijm): Investigate why checking >= End significantly changes
565 // output. Should not happen when renumbering produces monotonically
566 // increasing instruction numbers and live ranges begin and end on non-deleted
567 // instructions.
568 return Result;
569}
570}
571
572void TargetLowering::postRegallocSplitting(const SmallBitVector &RegMask) {
573 // Splits the live ranges of global(/multi block) variables and runs the
574 // register allocator to find registers for as many of the new variables as
575 // possible.
576 // TODO(manasijm): Merge the small liveranges back into multi-block ones when
577 // the variables get the same register. This will reduce the amount of new
578 // instructions inserted. This might involve a full dataflow analysis.
579 // Also, modify the preference mechanism in the register allocator to match.
580
581 TimerMarker _(TimerStack::TT_splitGlobalVars, Func);
582 CfgSet<Variable *> SplitCandidates;
583
584 // Find variables that do not have registers but are allowed to. Also skip
585 // variables with single segment live ranges as they are not split further in
586 // this function.
587 for (Variable *Var : Func->getVariables()) {
588 if (!Var->mustNotHaveReg() && !Var->hasReg()) {
589 if (Var->getLiveRange().getNumSegments() > 1)
590 SplitCandidates.insert(Var);
591 }
592 }
593 if (SplitCandidates.empty())
594 return;
595
596 CfgSet<Variable *> ExtraVars;
597
598 struct UseInfo {
599 Variable *Replacing = nullptr;
600 Inst *FirstUse = nullptr;
601 Inst *LastDef = nullptr;
602 SizeT UseCount = 0;
603 };
604 CfgUnorderedMap<Variable *, UseInfo> VarInfo;
605 // Split the live ranges of the viable variables by node.
606 // Compute metadata (UseInfo) for each of the resulting variables.
607 for (auto *Var : SplitCandidates) {
608 for (auto &Segment : Var->getLiveRange().getSegments()) {
609 UseInfo Info;
610 Info.Replacing = Var;
611 auto *Node = Var->getLiveRange().getNodeForSegment(Segment.first);
612
613 for (auto *Instr :
614 getInstructionsInRange(Node, Segment.first, Segment.second)) {
615 for (SizeT i = 0; i < Instr->getSrcSize(); ++i) {
616 // It's safe to iterate over the top-level src operands rather than
617 // using FOREACH_VAR_IN_INST(), because any variables inside e.g.
618 // mem operands should already have registers.
619 if (auto *Var = llvm::dyn_cast<Variable>(Instr->getSrc(i))) {
620 if (Var == Info.Replacing) {
621 if (Info.FirstUse == nullptr && !llvm::isa<InstPhi>(Instr)) {
622 Info.FirstUse = Instr;
623 }
624 Info.UseCount++;
625 }
626 }
627 }
628 if (Instr->getDest() == Info.Replacing && !llvm::isa<InstPhi>(Instr)) {
629 Info.LastDef = Instr;
630 }
631 }
632
633 static constexpr SizeT MinUseThreshold = 3;
634 // Skip if variable has less than `MinUseThreshold` uses in the segment.
635 if (Info.UseCount < MinUseThreshold)
636 continue;
637
638 if (!Info.FirstUse && !Info.LastDef) {
639 continue;
640 }
641
642 LiveRange LR;
643 LR.addSegment(Segment);
644 Variable *NewVar = Func->makeVariable(Var->getType());
645
646 NewVar->setLiveRange(LR);
647
648 VarInfo[NewVar] = Info;
649
650 ExtraVars.insert(NewVar);
651 }
652 }
653 // Run the register allocator with all these new variables included
654 LinearScan RegAlloc(Func);
655 RegAlloc.init(RAK_Global, SplitCandidates);
656 RegAlloc.scan(RegMask, getFlags().getRandomizeRegisterAllocation());
657
658 // Modify the Cfg to use the new variables that now have registers.
659 for (auto *ExtraVar : ExtraVars) {
660 if (!ExtraVar->hasReg()) {
661 continue;
662 }
663
664 auto &Info = VarInfo[ExtraVar];
665
666 assert(ExtraVar->getLiveRange().getSegments().size() == 1);
667 auto Segment = ExtraVar->getLiveRange().getSegments()[0];
668
669 auto *Node =
670 Info.Replacing->getLiveRange().getNodeForSegment(Segment.first);
671
672 auto RelevantInsts =
673 getInstructionsInRange(Node, Segment.first, Segment.second);
674
675 if (RelevantInsts.empty())
676 continue;
677
678 // Replace old variables
679 for (auto *Instr : RelevantInsts) {
680 if (llvm::isa<InstPhi>(Instr))
681 continue;
682 // TODO(manasijm): Figure out how to safely enable replacing phi dest
683 // variables. The issue is that we can not insert low level mov
684 // instructions into the PhiList.
685 for (SizeT i = 0; i < Instr->getSrcSize(); ++i) {
686 // FOREACH_VAR_IN_INST() not needed. Same logic as above.
687 if (auto *Var = llvm::dyn_cast<Variable>(Instr->getSrc(i))) {
688 if (Var == Info.Replacing) {
689 Instr->replaceSource(i, ExtraVar);
690 }
691 }
692 }
693 if (Instr->getDest() == Info.Replacing) {
694 Instr->replaceDest(ExtraVar);
695 }
696 }
697
698 assert(Info.FirstUse != Info.LastDef);
699 assert(Info.FirstUse || Info.LastDef);
700
701 // Insert spill code
702 if (Info.FirstUse != nullptr) {
703 auto *NewInst =
704 Func->getTarget()->createLoweredMove(ExtraVar, Info.Replacing);
705 Node->getInsts().insert(instToIterator(Info.FirstUse), NewInst);
706 }
707 if (Info.LastDef != nullptr) {
708 auto *NewInst =
709 Func->getTarget()->createLoweredMove(Info.Replacing, ExtraVar);
710 Node->getInsts().insertAfter(instToIterator(Info.LastDef), NewInst);
711 }
712 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700713}
714
Jim Stichnoth230d4102015-09-25 17:40:32 -0700715void TargetLowering::markRedefinitions() {
716 // Find (non-SSA) instructions where the Dest variable appears in some source
717 // operand, and set the IsDestRedefined flag to keep liveness analysis
718 // consistent.
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800719 for (auto Instr = Context.getCur(), E = Context.getNext(); Instr != E;
720 ++Instr) {
721 if (Instr->isDeleted())
Jan Voungb3401d22015-05-18 09:38:21 -0700722 continue;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800723 Variable *Dest = Instr->getDest();
Jim Stichnoth230d4102015-09-25 17:40:32 -0700724 if (Dest == nullptr)
725 continue;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800726 FOREACH_VAR_IN_INST(Var, *Instr) {
Jim Stichnoth230d4102015-09-25 17:40:32 -0700727 if (Var == Dest) {
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800728 Instr->setDestRedefined();
Jim Stichnoth230d4102015-09-25 17:40:32 -0700729 break;
730 }
Jan Voungb3401d22015-05-18 09:38:21 -0700731 }
732 }
733}
734
Jim Stichnoth91c773e2016-01-19 09:52:22 -0800735void TargetLowering::addFakeDefUses(const Inst *Instr) {
736 FOREACH_VAR_IN_INST(Var, *Instr) {
737 if (auto *Var64 = llvm::dyn_cast<Variable64On32>(Var)) {
738 Context.insert<InstFakeUse>(Var64->getLo());
739 Context.insert<InstFakeUse>(Var64->getHi());
Jaydeep Patil958ddb72016-10-03 07:52:48 -0700740 } else if (auto *VarVec = llvm::dyn_cast<VariableVecOn32>(Var)) {
741 for (Variable *Var : VarVec->getContainers()) {
742 Context.insert<InstFakeUse>(Var);
743 }
Jim Stichnoth91c773e2016-01-19 09:52:22 -0800744 } else {
745 Context.insert<InstFakeUse>(Var);
746 }
747 }
748 Variable *Dest = Instr->getDest();
749 if (Dest == nullptr)
750 return;
751 if (auto *Var64 = llvm::dyn_cast<Variable64On32>(Dest)) {
752 Context.insert<InstFakeDef>(Var64->getLo());
753 Context.insert<InstFakeDef>(Var64->getHi());
Jaydeep Patil958ddb72016-10-03 07:52:48 -0700754 } else if (auto *VarVec = llvm::dyn_cast<VariableVecOn32>(Dest)) {
755 for (Variable *Var : VarVec->getContainers()) {
756 Context.insert<InstFakeDef>(Var);
757 }
Jim Stichnoth91c773e2016-01-19 09:52:22 -0800758 } else {
759 Context.insert<InstFakeDef>(Dest);
760 }
761}
762
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700763void TargetLowering::sortVarsByAlignment(VarList &Dest,
764 const VarList &Source) const {
765 Dest = Source;
Andrew Scull57e12682015-09-16 11:30:19 -0700766 // Instead of std::sort, we could do a bucket sort with log2(alignment) as
767 // the buckets, if performance is an issue.
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700768 std::sort(Dest.begin(), Dest.end(),
769 [this](const Variable *V1, const Variable *V2) {
Jim Stichnoth53dae722016-08-31 15:32:32 -0700770 const size_t WidthV1 = typeWidthInBytesOnStack(V1->getType());
771 const size_t WidthV2 = typeWidthInBytesOnStack(V2->getType());
772 if (WidthV1 == WidthV2)
773 return V1->getIndex() < V2->getIndex();
774 return WidthV1 > WidthV2;
Jim Stichnoth8e6bf6e2015-06-03 15:58:12 -0700775 });
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700776}
777
778void TargetLowering::getVarStackSlotParams(
John Portoe82b5602016-02-24 15:58:55 -0800779 VarList &SortedSpilledVariables, SmallBitVector &RegsUsed,
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700780 size_t *GlobalsSize, size_t *SpillAreaSizeBytes,
781 uint32_t *SpillAreaAlignmentBytes, uint32_t *LocalsSlotsAlignmentBytes,
782 std::function<bool(Variable *)> TargetVarHook) {
783 const VariablesMetadata *VMetadata = Func->getVMetadata();
John Porto36d6aa62016-02-26 07:19:59 -0800784 BitVector IsVarReferenced(Func->getNumVariables());
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700785 for (CfgNode *Node : Func->getNodes()) {
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800786 for (Inst &Instr : Node->getInsts()) {
787 if (Instr.isDeleted())
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700788 continue;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800789 if (const Variable *Var = Instr.getDest())
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700790 IsVarReferenced[Var->getIndex()] = true;
Jim Stichnoth8cfeb692016-02-05 09:50:02 -0800791 FOREACH_VAR_IN_INST(Var, Instr) {
John Portoec3f5652015-08-31 15:07:09 -0700792 IsVarReferenced[Var->getIndex()] = true;
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700793 }
794 }
795 }
796
Andrew Scull57e12682015-09-16 11:30:19 -0700797 // If SimpleCoalescing is false, each variable without a register gets its
798 // own unique stack slot, which leads to large stack frames. If
799 // SimpleCoalescing is true, then each "global" variable without a register
800 // gets its own slot, but "local" variable slots are reused across basic
801 // blocks. E.g., if A and B are local to block 1 and C is local to block 2,
802 // then C may share a slot with A or B.
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700803 //
804 // We cannot coalesce stack slots if this function calls a "returns twice"
Andrew Scull57e12682015-09-16 11:30:19 -0700805 // function. In that case, basic blocks may be revisited, and variables local
806 // to those basic blocks are actually live until after the called function
807 // returns a second time.
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700808 const bool SimpleCoalescing = !callsReturnsTwice();
809
John Portoe82b5602016-02-24 15:58:55 -0800810 CfgVector<size_t> LocalsSize(Func->getNumNodes());
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700811 const VarList &Variables = Func->getVariables();
812 VarList SpilledVariables;
813 for (Variable *Var : Variables) {
814 if (Var->hasReg()) {
David Sehr2f3b8ec2015-11-16 16:51:39 -0800815 // Don't consider a rematerializable variable to be an actual register use
816 // (specifically of the frame pointer). Otherwise, the prolog may decide
817 // to save the frame pointer twice - once because of the explicit need for
818 // a frame pointer, and once because of an active use of a callee-save
819 // register.
820 if (!Var->isRematerializable())
821 RegsUsed[Var->getRegNum()] = true;
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700822 continue;
823 }
Andrew Scull57e12682015-09-16 11:30:19 -0700824 // An argument either does not need a stack slot (if passed in a register)
825 // or already has one (if passed on the stack).
Jim Stichnothb9a84722016-08-01 13:18:36 -0700826 if (Var->getIsArg()) {
827 if (!Var->hasReg()) {
828 assert(!Var->hasStackOffset());
829 Var->setHasStackOffset();
830 }
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700831 continue;
Jim Stichnothb9a84722016-08-01 13:18:36 -0700832 }
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700833 // An unreferenced variable doesn't need a stack slot.
834 if (!IsVarReferenced[Var->getIndex()])
835 continue;
Andrew Scull57e12682015-09-16 11:30:19 -0700836 // Check a target-specific variable (it may end up sharing stack slots) and
837 // not need accounting here.
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700838 if (TargetVarHook(Var))
839 continue;
Jim Stichnothb9a84722016-08-01 13:18:36 -0700840 assert(!Var->hasStackOffset());
841 Var->setHasStackOffset();
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700842 SpilledVariables.push_back(Var);
843 }
844
845 SortedSpilledVariables.reserve(SpilledVariables.size());
846 sortVarsByAlignment(SortedSpilledVariables, SpilledVariables);
847
848 for (Variable *Var : SortedSpilledVariables) {
849 size_t Increment = typeWidthInBytesOnStack(Var->getType());
Andrew Scull57e12682015-09-16 11:30:19 -0700850 // We have sorted by alignment, so the first variable we encounter that is
851 // located in each area determines the max alignment for the area.
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700852 if (!*SpillAreaAlignmentBytes)
853 *SpillAreaAlignmentBytes = Increment;
854 if (SimpleCoalescing && VMetadata->isTracked(Var)) {
855 if (VMetadata->isMultiBlock(Var)) {
856 *GlobalsSize += Increment;
857 } else {
858 SizeT NodeIndex = VMetadata->getLocalUseNode(Var)->getIndex();
859 LocalsSize[NodeIndex] += Increment;
860 if (LocalsSize[NodeIndex] > *SpillAreaSizeBytes)
861 *SpillAreaSizeBytes = LocalsSize[NodeIndex];
862 if (!*LocalsSlotsAlignmentBytes)
863 *LocalsSlotsAlignmentBytes = Increment;
864 }
865 } else {
866 *SpillAreaSizeBytes += Increment;
867 }
868 }
Jan Voung28068ad2015-07-31 12:58:46 -0700869 // For testing legalization of large stack offsets on targets with limited
870 // offset bits in instruction encodings, add some padding.
Karl Schimpfd4699942016-04-02 09:55:31 -0700871 *SpillAreaSizeBytes += getFlags().getTestStackExtra();
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700872}
873
874void TargetLowering::alignStackSpillAreas(uint32_t SpillAreaStartOffset,
875 uint32_t SpillAreaAlignmentBytes,
876 size_t GlobalsSize,
877 uint32_t LocalsSlotsAlignmentBytes,
878 uint32_t *SpillAreaPaddingBytes,
879 uint32_t *LocalsSlotsPaddingBytes) {
880 if (SpillAreaAlignmentBytes) {
881 uint32_t PaddingStart = SpillAreaStartOffset;
882 uint32_t SpillAreaStart =
883 Utils::applyAlignment(PaddingStart, SpillAreaAlignmentBytes);
884 *SpillAreaPaddingBytes = SpillAreaStart - PaddingStart;
885 }
886
Andrew Scull57e12682015-09-16 11:30:19 -0700887 // If there are separate globals and locals areas, make sure the locals area
888 // is aligned by padding the end of the globals area.
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700889 if (LocalsSlotsAlignmentBytes) {
890 uint32_t GlobalsAndSubsequentPaddingSize = GlobalsSize;
891 GlobalsAndSubsequentPaddingSize =
892 Utils::applyAlignment(GlobalsSize, LocalsSlotsAlignmentBytes);
893 *LocalsSlotsPaddingBytes = GlobalsAndSubsequentPaddingSize - GlobalsSize;
894 }
895}
896
897void TargetLowering::assignVarStackSlots(VarList &SortedSpilledVariables,
898 size_t SpillAreaPaddingBytes,
899 size_t SpillAreaSizeBytes,
900 size_t GlobalsAndSubsequentPaddingSize,
901 bool UsesFramePointer) {
902 const VariablesMetadata *VMetadata = Func->getVMetadata();
Jan Voung28068ad2015-07-31 12:58:46 -0700903 // For testing legalization of large stack offsets on targets with limited
904 // offset bits in instruction encodings, add some padding. This assumes that
Andrew Scull57e12682015-09-16 11:30:19 -0700905 // SpillAreaSizeBytes has accounted for the extra test padding. When
906 // UseFramePointer is true, the offset depends on the padding, not just the
907 // SpillAreaSizeBytes. On the other hand, when UseFramePointer is false, the
908 // offsets depend on the gap between SpillAreaSizeBytes and
909 // SpillAreaPaddingBytes, so we don't increment that.
Karl Schimpfd4699942016-04-02 09:55:31 -0700910 size_t TestPadding = getFlags().getTestStackExtra();
Jan Voung28068ad2015-07-31 12:58:46 -0700911 if (UsesFramePointer)
912 SpillAreaPaddingBytes += TestPadding;
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700913 size_t GlobalsSpaceUsed = SpillAreaPaddingBytes;
914 size_t NextStackOffset = SpillAreaPaddingBytes;
John Portoe82b5602016-02-24 15:58:55 -0800915 CfgVector<size_t> LocalsSize(Func->getNumNodes());
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700916 const bool SimpleCoalescing = !callsReturnsTwice();
Jan Voung28068ad2015-07-31 12:58:46 -0700917
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700918 for (Variable *Var : SortedSpilledVariables) {
919 size_t Increment = typeWidthInBytesOnStack(Var->getType());
920 if (SimpleCoalescing && VMetadata->isTracked(Var)) {
921 if (VMetadata->isMultiBlock(Var)) {
922 GlobalsSpaceUsed += Increment;
923 NextStackOffset = GlobalsSpaceUsed;
924 } else {
925 SizeT NodeIndex = VMetadata->getLocalUseNode(Var)->getIndex();
926 LocalsSize[NodeIndex] += Increment;
927 NextStackOffset = SpillAreaPaddingBytes +
928 GlobalsAndSubsequentPaddingSize +
929 LocalsSize[NodeIndex];
930 }
931 } else {
932 NextStackOffset += Increment;
933 }
934 if (UsesFramePointer)
935 Var->setStackOffset(-NextStackOffset);
936 else
937 Var->setStackOffset(SpillAreaSizeBytes - NextStackOffset);
938 }
939}
940
Karl Schimpf20070e82016-03-17 13:30:13 -0700941InstCall *TargetLowering::makeHelperCall(RuntimeHelper FuncID, Variable *Dest,
Jan Voungb36ad9b2015-04-21 17:01:49 -0700942 SizeT MaxSrcs) {
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700943 constexpr bool HasTailCall = false;
Karl Schimpf20070e82016-03-17 13:30:13 -0700944 Constant *CallTarget = Ctx->getRuntimeHelperFunc(FuncID);
Jan Voungb36ad9b2015-04-21 17:01:49 -0700945 InstCall *Call =
946 InstCall::create(Func, MaxSrcs, Dest, CallTarget, HasTailCall);
947 return Call;
948}
949
Andrew Scullcfa628b2015-08-20 14:23:05 -0700950bool TargetLowering::shouldOptimizeMemIntrins() {
Jim Stichnoth386b52e2016-08-05 15:18:41 -0700951 return Func->getOptLevel() >= Opt_1 || getFlags().getForceMemIntrinOpt();
Andrew Scullcfa628b2015-08-20 14:23:05 -0700952}
953
Eric Holkcfc25532016-02-09 17:47:58 -0800954void TargetLowering::scalarizeArithmetic(InstArithmetic::OpKind Kind,
955 Variable *Dest, Operand *Src0,
956 Operand *Src1) {
Eric Holkcc69fa22016-02-10 13:07:06 -0800957 scalarizeInstruction(
Eric Holkd6cf6b32016-02-17 11:09:48 -0800958 Dest, [this, Kind](Variable *Dest, Operand *Src0, Operand *Src1) {
Eric Holkcc69fa22016-02-10 13:07:06 -0800959 return Context.insert<InstArithmetic>(Kind, Dest, Src0, Src1);
Eric Holkd6cf6b32016-02-17 11:09:48 -0800960 }, Src0, Src1);
Eric Holkcfc25532016-02-09 17:47:58 -0800961}
962
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800963void TargetLowering::emitWithoutPrefix(const ConstantRelocatable *C,
964 const char *Suffix) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700965 if (!BuildDefs::dump())
Jan Voung76bb0be2015-05-14 09:26:19 -0700966 return;
967 Ostream &Str = Ctx->getStrEmit();
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700968 const std::string &EmitStr = C->getEmitString();
John Porto27fddcc2016-02-02 15:06:09 -0800969 if (!EmitStr.empty()) {
970 // C has a custom emit string, so we use it instead of the canonical
971 // Name + Offset form.
972 Str << EmitStr;
973 return;
974 }
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800975 Str << C->getName() << Suffix;
Jan Voung76bb0be2015-05-14 09:26:19 -0700976 RelocOffsetT Offset = C->getOffset();
977 if (Offset) {
978 if (Offset > 0)
979 Str << "+";
980 Str << Offset;
981 }
982}
983
Jim Stichnothbbca7542015-02-11 16:08:31 -0800984std::unique_ptr<TargetDataLowering>
985TargetDataLowering::createLowering(GlobalContext *Ctx) {
Karl Schimpfd4699942016-04-02 09:55:31 -0700986 TargetArch Target = getFlags().getTargetArch();
John Porto53611e22015-12-30 07:30:10 -0800987 switch (Target) {
988 default:
Jim Stichnoth816fd682016-02-16 05:47:32 -0800989 badTargetFatalError(Target);
Jan Voungb36ad9b2015-04-21 17:01:49 -0700990#define SUBZERO_TARGET(X) \
Jim Stichnoth999a22f2016-03-12 10:22:53 -0800991 case TARGET_LOWERING_CLASS_FOR(X): \
John Porto53611e22015-12-30 07:30:10 -0800992 return ::X::createTargetDataLowering(Ctx);
Jim Stichnoth999a22f2016-03-12 10:22:53 -0800993#include "SZTargets.def"
John Porto53611e22015-12-30 07:30:10 -0800994#undef SUBZERO_TARGET
995 }
Jim Stichnothde4ca712014-06-29 08:13:48 -0700996}
997
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700998TargetDataLowering::~TargetDataLowering() = default;
Jan Voung839c4ce2014-07-28 15:19:43 -0700999
John Porto8b1a7052015-06-17 13:20:08 -07001000namespace {
1001
Jim Stichnoth98ba0062016-03-07 09:26:22 -08001002// dataSectionSuffix decides whether to use SectionSuffix or VarName as data
1003// section suffix. Essentially, when using separate data sections for globals
1004// SectionSuffix is not necessary.
Jim Stichnoth467ffe52016-03-29 15:01:06 -07001005std::string dataSectionSuffix(const std::string &SectionSuffix,
1006 const std::string &VarName,
1007 const bool DataSections) {
John Porto8b1a7052015-06-17 13:20:08 -07001008 if (SectionSuffix.empty() && !DataSections) {
1009 return "";
1010 }
1011
1012 if (DataSections) {
1013 // With data sections we don't need to use the SectionSuffix.
Jim Stichnoth98ba0062016-03-07 09:26:22 -08001014 return "." + VarName;
John Porto8b1a7052015-06-17 13:20:08 -07001015 }
1016
1017 assert(!SectionSuffix.empty());
1018 return "." + SectionSuffix;
1019}
1020
1021} // end of anonymous namespace
1022
1023void TargetDataLowering::emitGlobal(const VariableDeclaration &Var,
Jim Stichnoth467ffe52016-03-29 15:01:06 -07001024 const std::string &SectionSuffix) {
Jim Stichnoth20b71f52015-06-24 15:52:24 -07001025 if (!BuildDefs::dump())
Jan Voung58eea4d2015-06-15 15:11:56 -07001026 return;
1027
Andrew Scull57e12682015-09-16 11:30:19 -07001028 // If external and not initialized, this must be a cross test. Don't generate
1029 // a declaration for such cases.
Karl Schimpfd4699942016-04-02 09:55:31 -07001030 const bool IsExternal = Var.isExternal() || getFlags().getDisableInternal();
Jan Voung58eea4d2015-06-15 15:11:56 -07001031 if (IsExternal && !Var.hasInitializer())
1032 return;
1033
1034 Ostream &Str = Ctx->getStrEmit();
John Porto8b1a7052015-06-17 13:20:08 -07001035 const bool HasNonzeroInitializer = Var.hasNonzeroInitializer();
1036 const bool IsConstant = Var.getIsConstant();
1037 const SizeT Size = Var.getNumBytes();
Jim Stichnoth467ffe52016-03-29 15:01:06 -07001038 const std::string Name = Var.getName().toString();
Jan Voung58eea4d2015-06-15 15:11:56 -07001039
Jim Stichnoth98ba0062016-03-07 09:26:22 -08001040 Str << "\t.type\t" << Name << ",%object\n";
Jan Voung58eea4d2015-06-15 15:11:56 -07001041
Karl Schimpfd4699942016-04-02 09:55:31 -07001042 const bool UseDataSections = getFlags().getDataSections();
1043 const bool UseNonsfi = getFlags().getUseNonsfi();
Jim Stichnoth467ffe52016-03-29 15:01:06 -07001044 const std::string Suffix =
Jim Stichnoth98ba0062016-03-07 09:26:22 -08001045 dataSectionSuffix(SectionSuffix, Name, UseDataSections);
Jim Stichnoth8ff4b282016-01-04 15:39:06 -08001046 if (IsConstant && UseNonsfi)
1047 Str << "\t.section\t.data.rel.ro" << Suffix << ",\"aw\",%progbits\n";
1048 else if (IsConstant)
John Porto8b1a7052015-06-17 13:20:08 -07001049 Str << "\t.section\t.rodata" << Suffix << ",\"a\",%progbits\n";
Jan Voung58eea4d2015-06-15 15:11:56 -07001050 else if (HasNonzeroInitializer)
John Porto8b1a7052015-06-17 13:20:08 -07001051 Str << "\t.section\t.data" << Suffix << ",\"aw\",%progbits\n";
Jan Voung58eea4d2015-06-15 15:11:56 -07001052 else
John Porto8b1a7052015-06-17 13:20:08 -07001053 Str << "\t.section\t.bss" << Suffix << ",\"aw\",%nobits\n";
Jan Voung58eea4d2015-06-15 15:11:56 -07001054
1055 if (IsExternal)
Jim Stichnoth98ba0062016-03-07 09:26:22 -08001056 Str << "\t.globl\t" << Name << "\n";
Jan Voung58eea4d2015-06-15 15:11:56 -07001057
John Porto8b1a7052015-06-17 13:20:08 -07001058 const uint32_t Align = Var.getAlignment();
Jan Voung58eea4d2015-06-15 15:11:56 -07001059 if (Align > 1) {
1060 assert(llvm::isPowerOf2_32(Align));
1061 // Use the .p2align directive, since the .align N directive can either
1062 // interpret N as bytes, or power of 2 bytes, depending on the target.
1063 Str << "\t.p2align\t" << llvm::Log2_32(Align) << "\n";
1064 }
1065
Jim Stichnoth98ba0062016-03-07 09:26:22 -08001066 Str << Name << ":\n";
Jan Voung58eea4d2015-06-15 15:11:56 -07001067
1068 if (HasNonzeroInitializer) {
John Portoa78e4ba2016-03-15 09:28:04 -07001069 for (const auto *Init : Var.getInitializers()) {
Jan Voung58eea4d2015-06-15 15:11:56 -07001070 switch (Init->getKind()) {
1071 case VariableDeclaration::Initializer::DataInitializerKind: {
Jan Vounge0df91f2015-06-30 08:47:06 -07001072 const auto &Data =
John Portoa78e4ba2016-03-15 09:28:04 -07001073 llvm::cast<VariableDeclaration::DataInitializer>(Init)
Jan Vounge0df91f2015-06-30 08:47:06 -07001074 ->getContents();
Jan Voung58eea4d2015-06-15 15:11:56 -07001075 for (SizeT i = 0; i < Init->getNumBytes(); ++i) {
1076 Str << "\t.byte\t" << (((unsigned)Data[i]) & 0xff) << "\n";
1077 }
1078 break;
1079 }
1080 case VariableDeclaration::Initializer::ZeroInitializerKind:
1081 Str << "\t.zero\t" << Init->getNumBytes() << "\n";
1082 break;
1083 case VariableDeclaration::Initializer::RelocInitializerKind: {
John Porto8b1a7052015-06-17 13:20:08 -07001084 const auto *Reloc =
John Portoa78e4ba2016-03-15 09:28:04 -07001085 llvm::cast<VariableDeclaration::RelocInitializer>(Init);
Jan Voung58eea4d2015-06-15 15:11:56 -07001086 Str << "\t" << getEmit32Directive() << "\t";
Jim Stichnoth98ba0062016-03-07 09:26:22 -08001087 Str << Reloc->getDeclaration()->getName();
John Portodc619252016-02-10 15:57:16 -08001088 if (Reloc->hasFixup()) {
1089 // TODO(jpp): this is ARM32 specific.
1090 Str << "(GOTOFF)";
1091 }
Jan Voung58eea4d2015-06-15 15:11:56 -07001092 if (RelocOffsetT Offset = Reloc->getOffset()) {
1093 if (Offset >= 0 || (Offset == INT32_MIN))
1094 Str << " + " << Offset;
1095 else
1096 Str << " - " << -Offset;
1097 }
1098 Str << "\n";
1099 break;
1100 }
1101 }
1102 }
John Porto8b1a7052015-06-17 13:20:08 -07001103 } else {
Andrew Scull57e12682015-09-16 11:30:19 -07001104 // NOTE: for non-constant zero initializers, this is BSS (no bits), so an
1105 // ELF writer would not write to the file, and only track virtual offsets,
1106 // but the .s writer still needs this .zero and cannot simply use the .size
1107 // to advance offsets.
Jan Voung58eea4d2015-06-15 15:11:56 -07001108 Str << "\t.zero\t" << Size << "\n";
John Porto8b1a7052015-06-17 13:20:08 -07001109 }
Jan Voung58eea4d2015-06-15 15:11:56 -07001110
Jim Stichnoth98ba0062016-03-07 09:26:22 -08001111 Str << "\t.size\t" << Name << ", " << Size << "\n";
Jan Voung58eea4d2015-06-15 15:11:56 -07001112}
1113
Jan Voungfb792842015-06-11 15:27:50 -07001114std::unique_ptr<TargetHeaderLowering>
1115TargetHeaderLowering::createLowering(GlobalContext *Ctx) {
Karl Schimpfd4699942016-04-02 09:55:31 -07001116 TargetArch Target = getFlags().getTargetArch();
John Porto53611e22015-12-30 07:30:10 -08001117 switch (Target) {
1118 default:
Jim Stichnoth816fd682016-02-16 05:47:32 -08001119 badTargetFatalError(Target);
Jan Voungfb792842015-06-11 15:27:50 -07001120#define SUBZERO_TARGET(X) \
Jim Stichnoth999a22f2016-03-12 10:22:53 -08001121 case TARGET_LOWERING_CLASS_FOR(X): \
John Porto53611e22015-12-30 07:30:10 -08001122 return ::X::createTargetHeaderLowering(Ctx);
Jim Stichnoth999a22f2016-03-12 10:22:53 -08001123#include "SZTargets.def"
John Porto53611e22015-12-30 07:30:10 -08001124#undef SUBZERO_TARGET
1125 }
Jan Voungfb792842015-06-11 15:27:50 -07001126}
1127
Jim Stichnotheafb56c2015-06-22 10:35:22 -07001128TargetHeaderLowering::~TargetHeaderLowering() = default;
Jan Voungfb792842015-06-11 15:27:50 -07001129
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001130} // end of namespace Ice