blob: 12de45274e441f3631f8c0467d13feeca7f59d20 [file] [log] [blame]
Jim Stichnothf7c9a142014-04-29 10:52:43 -07001//===- subzero/src/IceCfg.cpp - Control flow graph 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//===----------------------------------------------------------------------===//
9//
10// This file implements the Cfg class, including constant pool
11// management.
12//
13//===----------------------------------------------------------------------===//
14
John Portoaff4ccf2015-06-10 16:35:06 -070015#include "IceAssembler.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070016#include "IceCfg.h"
17#include "IceCfgNode.h"
Jim Stichnoth989a7032014-08-08 10:13:44 -070018#include "IceClFlags.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070019#include "IceDefs.h"
Jan Voungec270732015-01-12 17:00:22 -080020#include "IceELFObjectWriter.h"
John Portof8b4cc82015-06-09 18:06:19 -070021#include "IceGlobalInits.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070022#include "IceInst.h"
Jim Stichnothd97c7df2014-06-04 11:57:08 -070023#include "IceLiveness.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070024#include "IceOperand.h"
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070025#include "IceTargetLowering.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070026
27namespace Ice {
28
Jim Stichnotha5fe17a2015-01-26 11:10:03 -080029ICE_TLS_DEFINE_FIELD(const Cfg *, Cfg, CurrentCfg);
Jim Stichnoth31c95592014-12-19 12:51:35 -080030
Jan Voung1d62cf02015-01-09 14:57:32 -080031ArenaAllocator<> *getCurrentCfgAllocator() {
Jim Stichnoth31c95592014-12-19 12:51:35 -080032 return Cfg::getCurrentCfgAllocator();
33}
34
Jim Stichnothbbca7542015-02-11 16:08:31 -080035Cfg::Cfg(GlobalContext *Ctx, uint32_t SequenceNumber)
Jan Voung1f47ad02015-03-20 15:01:26 -070036 : Ctx(Ctx), SequenceNumber(SequenceNumber),
37 VMask(Ctx->getFlags().getVerbose()), FunctionName(""),
38 ReturnType(IceType_void), IsInternalLinkage(false), HasError(false),
39 FocusedTiming(false), ErrorMessage(""), Entry(nullptr),
Jim Stichnothfa4efea2015-01-27 05:06:03 -080040 NextInstNumber(Inst::NumberInitial), Allocator(new ArenaAllocator<>()),
Jan Voung1f47ad02015-03-20 15:01:26 -070041 Live(nullptr), Target(TargetLowering::createLowering(
42 Ctx->getFlags().getTargetArch(), this)),
Jan Voung8acded02014-09-22 18:02:25 -070043 VMetadata(new VariablesMetadata(this)),
Jan Voung1f47ad02015-03-20 15:01:26 -070044 TargetAssembler(TargetLowering::createAssembler(
45 Ctx->getFlags().getTargetArch(), this)),
Jim Stichnothae953202014-12-20 06:17:49 -080046 CurrentNode(nullptr) {
Karl Schimpf6fcbddd2014-11-06 09:49:24 -080047 assert(!Ctx->isIRGenerationDisabled() &&
48 "Attempt to build cfg when IR generation disabled");
49}
Jim Stichnothf7c9a142014-04-29 10:52:43 -070050
Jim Stichnoth8e928382015-02-02 17:03:08 -080051Cfg::~Cfg() { assert(ICE_TLS_GET_FIELD(CurrentCfg) == nullptr); }
Jim Stichnothf7c9a142014-04-29 10:52:43 -070052
53void Cfg::setError(const IceString &Message) {
54 HasError = true;
55 ErrorMessage = Message;
Jim Stichnothf7c9a142014-04-29 10:52:43 -070056}
57
Jim Stichnoth668a7a32014-12-10 15:32:25 -080058CfgNode *Cfg::makeNode() {
Jim Stichnothf7c9a142014-04-29 10:52:43 -070059 SizeT LabelIndex = Nodes.size();
Jim Stichnoth668a7a32014-12-10 15:32:25 -080060 CfgNode *Node = CfgNode::create(this, LabelIndex);
Jim Stichnothf7c9a142014-04-29 10:52:43 -070061 Nodes.push_back(Node);
62 return Node;
63}
64
Jim Stichnothf7c9a142014-04-29 10:52:43 -070065void Cfg::addArg(Variable *Arg) {
Jim Stichnoth144cdce2014-09-22 16:02:59 -070066 Arg->setIsArg();
Jim Stichnothf7c9a142014-04-29 10:52:43 -070067 Args.push_back(Arg);
68}
69
Jim Stichnoth144cdce2014-09-22 16:02:59 -070070void Cfg::addImplicitArg(Variable *Arg) {
71 Arg->setIsImplicitArg();
72 ImplicitArgs.push_back(Arg);
73}
74
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070075// Returns whether the stack frame layout has been computed yet. This
76// is used for dumping the stack frame location of Variables.
77bool Cfg::hasComputedFrame() const { return getTarget()->hasComputedFrame(); }
78
John Portof8b4cc82015-06-09 18:06:19 -070079namespace {
80constexpr char BlockNameGlobalPrefix[] = ".L$profiler$block_name$";
81constexpr char BlockStatsGlobalPrefix[] = ".L$profiler$block_info$";
82
83VariableDeclaration *nodeNameDeclaration(const IceString &NodeAsmName) {
84 VariableDeclaration *Var = VariableDeclaration::create();
85 Var->setName(BlockNameGlobalPrefix + NodeAsmName);
86 Var->setIsConstant(true);
87 Var->addInitializer(new VariableDeclaration::DataInitializer(
88 NodeAsmName.data(), NodeAsmName.size() + 1));
89 const SizeT Int64ByteSize = typeWidthInBytes(IceType_i64);
90 Var->setAlignment(Int64ByteSize); // Wasteful, 32-bit could use 4 bytes.
91 return Var;
92}
93
94VariableDeclaration *
95blockProfilingInfoDeclaration(const IceString &NodeAsmName,
96 VariableDeclaration *NodeNameDeclaration) {
97 VariableDeclaration *Var = VariableDeclaration::create();
98 Var->setName(BlockStatsGlobalPrefix + NodeAsmName);
99 const SizeT Int64ByteSize = typeWidthInBytes(IceType_i64);
100 Var->addInitializer(new VariableDeclaration::ZeroInitializer(Int64ByteSize));
101
102 const RelocOffsetT NodeNameDeclarationOffset = 0;
103 Var->addInitializer(new VariableDeclaration::RelocInitializer(
104 NodeNameDeclaration, NodeNameDeclarationOffset));
105 Var->setAlignment(Int64ByteSize);
106 return Var;
107}
108
109} // end of anonymous namespace
110
111void Cfg::profileBlocks() {
112 if (GlobalInits == nullptr)
113 GlobalInits.reset(new VariableDeclarationList());
114
115 for (CfgNode *Node : Nodes) {
116 IceString NodeAsmName = Node->getAsmName();
117 GlobalInits->push_back(nodeNameDeclaration(NodeAsmName));
118 GlobalInits->push_back(
119 blockProfilingInfoDeclaration(NodeAsmName, GlobalInits->back()));
120 Node->profileExecutionCount(GlobalInits->back());
121 }
122}
123
124bool Cfg::isProfileGlobal(const VariableDeclaration &Var) {
125 return Var.getName().find(BlockStatsGlobalPrefix) == 0;
126}
127
128void Cfg::addCallToProfileSummary() {
129 // The call(s) to __Sz_profile_summary are added by the profiler in functions
130 // that cause the program to exit. This function is defined in
131 // runtime/szrt_profiler.c.
132 Constant *ProfileSummarySym =
133 Ctx->getConstantExternSym("__Sz_profile_summary");
134 constexpr SizeT NumArgs = 0;
135 constexpr Variable *Void = nullptr;
136 constexpr bool HasTailCall = false;
137 auto *Call =
138 InstCall::create(this, NumArgs, Void, ProfileSummarySym, HasTailCall);
139 getEntryNode()->getInsts().push_front(Call);
140}
141
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700142void Cfg::translate() {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700143 if (hasError())
144 return;
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800145 // FunctionTimer conditionally pushes/pops a TimerMarker if
146 // TimeEachFunction is enabled.
147 std::unique_ptr<TimerMarker> FunctionTimer;
Jim Stichnoth1c44d812014-12-08 14:57:52 -0800148 if (ALLOW_DUMP) {
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800149 const IceString &TimingFocusOn =
150 getContext()->getFlags().getTimingFocusOn();
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800151 const IceString &Name = getFunctionName();
152 if (TimingFocusOn == "*" || TimingFocusOn == Name) {
Jim Stichnoth1c44d812014-12-08 14:57:52 -0800153 setFocusedTiming();
154 getContext()->resetTimer(GlobalContext::TSK_Default);
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800155 getContext()->setTimerName(GlobalContext::TSK_Default, Name);
Jim Stichnoth1c44d812014-12-08 14:57:52 -0800156 }
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800157 if (getContext()->getFlags().getTimeEachFunction())
Jim Stichnoth380d7b92015-01-30 13:10:39 -0800158 FunctionTimer.reset(new TimerMarker(
159 getContext()->getTimerID(GlobalContext::TSK_Funcs, Name),
160 getContext(), GlobalContext::TSK_Funcs));
Jim Stichnothd14b1a02014-10-08 08:28:36 -0700161 }
Jim Stichnoth8363a062014-10-07 10:02:38 -0700162 TimerMarker T(TimerStack::TT_translate, this);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700163
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700164 dump("Initial CFG");
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700165
John Portof8b4cc82015-06-09 18:06:19 -0700166 if (getContext()->getFlags().getEnableBlockProfile()) {
167 profileBlocks();
168 // TODO(jpp): this is fragile, at best. Figure out a better way of detecting
169 // exit functions.
170 if (GlobalContext::matchSymbolName(getFunctionName(), "exit")) {
171 addCallToProfileSummary();
172 }
173 dump("Profiled CFG");
174 }
175
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700176 // The set of translation passes and their order are determined by
177 // the target.
178 getTarget()->translate();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700179
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700180 dump("Final output");
Jim Stichnoth8363a062014-10-07 10:02:38 -0700181 if (getFocusedTiming())
182 getContext()->dumpTimers();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700183}
184
Jim Stichnoth69d3f9c2015-03-23 10:33:38 -0700185void Cfg::computeInOutEdges() {
186 // Compute the out-edges.
Jim Stichnothf44f3712014-10-01 14:05:51 -0700187 for (CfgNode *Node : Nodes)
Jim Stichnoth69d3f9c2015-03-23 10:33:38 -0700188 Node->computeSuccessors();
189
190 // Prune any unreachable nodes before computing in-edges.
191 SizeT NumNodes = getNumNodes();
192 llvm::BitVector Reachable(NumNodes);
193 llvm::BitVector Pending(NumNodes);
194 Pending.set(getEntryNode()->getIndex());
195 while (true) {
196 int Index = Pending.find_first();
197 if (Index == -1)
198 break;
199 Pending.reset(Index);
200 Reachable.set(Index);
201 CfgNode *Node = Nodes[Index];
202 assert(Node->getIndex() == (SizeT)Index);
203 for (CfgNode *Succ : Node->getOutEdges()) {
204 SizeT SuccIndex = Succ->getIndex();
205 if (!Reachable.test(SuccIndex))
206 Pending.set(SuccIndex);
207 }
208 }
209 SizeT Dest = 0;
210 for (SizeT Source = 0; Source < NumNodes; ++Source) {
211 if (Reachable.test(Source)) {
212 Nodes[Dest] = Nodes[Source];
213 Nodes[Dest]->resetIndex(Dest);
214 // Compute the in-edges.
215 Nodes[Dest]->computePredecessors();
216 ++Dest;
217 }
218 }
219 Nodes.resize(Dest);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700220}
221
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700222void Cfg::renumberInstructions() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700223 TimerMarker T(TimerStack::TT_renumberInstructions, this);
Jim Stichnothe5b73e62014-12-15 09:58:51 -0800224 NextInstNumber = Inst::NumberInitial;
Jim Stichnothf44f3712014-10-01 14:05:51 -0700225 for (CfgNode *Node : Nodes)
226 Node->renumberInstructions();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700227}
228
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700229// placePhiLoads() must be called before placePhiStores().
230void Cfg::placePhiLoads() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700231 TimerMarker T(TimerStack::TT_placePhiLoads, this);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700232 for (CfgNode *Node : Nodes)
233 Node->placePhiLoads();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700234}
235
236// placePhiStores() must be called after placePhiLoads().
237void Cfg::placePhiStores() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700238 TimerMarker T(TimerStack::TT_placePhiStores, this);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700239 for (CfgNode *Node : Nodes)
240 Node->placePhiStores();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700241}
242
243void Cfg::deletePhis() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700244 TimerMarker T(TimerStack::TT_deletePhis, this);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700245 for (CfgNode *Node : Nodes)
246 Node->deletePhis();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700247}
248
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700249void Cfg::advancedPhiLowering() {
250 TimerMarker T(TimerStack::TT_advancedPhiLowering, this);
251 // This splits edges and appends new nodes to the end of the node
252 // list. This can invalidate iterators, so don't use an iterator.
253 SizeT NumNodes = getNumNodes();
254 for (SizeT I = 0; I < NumNodes; ++I)
255 Nodes[I]->advancedPhiLowering();
256}
257
258// Find a reasonable placement for nodes that have not yet been
259// placed, while maintaining the same relative ordering among already
260// placed nodes.
261void Cfg::reorderNodes() {
262 typedef std::list<CfgNode *> PlacedList;
263 PlacedList Placed; // Nodes with relative placement locked down
264 PlacedList Unreachable; // Unreachable nodes
265 PlacedList::iterator NoPlace = Placed.end();
266 // Keep track of where each node has been tentatively placed so that
267 // we can manage insertions into the middle.
268 std::vector<PlacedList::iterator> PlaceIndex(Nodes.size(), NoPlace);
269 for (CfgNode *Node : Nodes) {
270 // The "do ... while(0);" construct is to factor out the
271 // --PlaceIndex and assert() statements before moving to the next
272 // node.
273 do {
274 if (!Node->needsPlacement()) {
275 // Add to the end of the Placed list.
276 Placed.push_back(Node);
277 PlaceIndex[Node->getIndex()] = Placed.end();
278 continue;
279 }
280 Node->setNeedsPlacement(false);
Jim Stichnothbfb410d2014-11-05 16:04:05 -0800281 if (Node != getEntryNode() && Node->getInEdges().empty()) {
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700282 // The node has essentially been deleted since it is not a
283 // successor of any other node.
284 Unreachable.push_back(Node);
285 PlaceIndex[Node->getIndex()] = Unreachable.end();
286 continue;
287 }
288 // Assume for now that the unplaced node is from edge-splitting
289 // and therefore has 1 in-edge and 1 out-edge (actually, possibly
290 // more than 1 in-edge if the predecessor node was contracted).
291 // If this changes in the future, rethink the strategy.
292 assert(Node->getInEdges().size() >= 1);
293 assert(Node->getOutEdges().size() == 1);
294
295 // If it's a (non-critical) edge where the successor has a single
296 // in-edge, then place it before the successor.
Jim Stichnothbfb410d2014-11-05 16:04:05 -0800297 CfgNode *Succ = Node->getOutEdges().front();
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700298 if (Succ->getInEdges().size() == 1 &&
299 PlaceIndex[Succ->getIndex()] != NoPlace) {
300 Placed.insert(PlaceIndex[Succ->getIndex()], Node);
301 PlaceIndex[Node->getIndex()] = PlaceIndex[Succ->getIndex()];
302 continue;
303 }
304
305 // Otherwise, place it after the (first) predecessor.
Jim Stichnothbfb410d2014-11-05 16:04:05 -0800306 CfgNode *Pred = Node->getInEdges().front();
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700307 auto PredPosition = PlaceIndex[Pred->getIndex()];
308 // It shouldn't be the case that PredPosition==NoPlace, but if
309 // that somehow turns out to be true, we just insert Node before
310 // PredPosition=NoPlace=Placed.end() .
311 if (PredPosition != NoPlace)
312 ++PredPosition;
313 Placed.insert(PredPosition, Node);
314 PlaceIndex[Node->getIndex()] = PredPosition;
315 } while (0);
316
317 --PlaceIndex[Node->getIndex()];
318 assert(*PlaceIndex[Node->getIndex()] == Node);
319 }
320
321 // Reorder Nodes according to the built-up lists.
Jim Stichnothbfb410d2014-11-05 16:04:05 -0800322 SizeT OldSize = Nodes.size();
323 (void)OldSize;
324 Nodes.clear();
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700325 for (CfgNode *Node : Placed)
Jim Stichnothbfb410d2014-11-05 16:04:05 -0800326 Nodes.push_back(Node);
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700327 for (CfgNode *Node : Unreachable)
Jim Stichnothbfb410d2014-11-05 16:04:05 -0800328 Nodes.push_back(Node);
329 assert(Nodes.size() == OldSize);
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700330}
331
Matt Wala45a06232014-07-09 16:33:22 -0700332void Cfg::doArgLowering() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700333 TimerMarker T(TimerStack::TT_doArgLowering, this);
Matt Wala45a06232014-07-09 16:33:22 -0700334 getTarget()->lowerArguments();
335}
336
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700337void Cfg::doAddressOpt() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700338 TimerMarker T(TimerStack::TT_doAddressOpt, this);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700339 for (CfgNode *Node : Nodes)
340 Node->doAddressOpt();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700341}
342
Matt Walac3302742014-08-15 16:21:56 -0700343void Cfg::doNopInsertion() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700344 TimerMarker T(TimerStack::TT_doNopInsertion, this);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700345 for (CfgNode *Node : Nodes)
346 Node->doNopInsertion();
Matt Walac3302742014-08-15 16:21:56 -0700347}
348
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700349void Cfg::genCode() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700350 TimerMarker T(TimerStack::TT_genCode, this);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700351 for (CfgNode *Node : Nodes)
352 Node->genCode();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700353}
354
355// Compute the stack frame layout.
356void Cfg::genFrame() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700357 TimerMarker T(TimerStack::TT_genFrame, this);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700358 getTarget()->addProlog(Entry);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700359 for (CfgNode *Node : Nodes)
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700360 if (Node->getHasReturn())
361 getTarget()->addEpilog(Node);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700362}
363
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700364// This is a lightweight version of live-range-end calculation. Marks
365// the last use of only those variables whose definition and uses are
366// completely with a single block. It is a quick single pass and
367// doesn't need to iterate until convergence.
368void Cfg::livenessLightweight() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700369 TimerMarker T(TimerStack::TT_livenessLightweight, this);
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700370 getVMetadata()->init(VMK_Uses);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700371 for (CfgNode *Node : Nodes)
372 Node->livenessLightweight();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700373}
374
375void Cfg::liveness(LivenessMode Mode) {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700376 TimerMarker T(TimerStack::TT_liveness, this);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700377 Live.reset(new Liveness(this, Mode));
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700378 getVMetadata()->init(VMK_Uses);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700379 Live->init();
380 // Initialize with all nodes needing to be processed.
381 llvm::BitVector NeedToProcess(Nodes.size(), true);
382 while (NeedToProcess.any()) {
383 // Iterate in reverse topological order to speed up convergence.
Jim Stichnoth7e571362015-01-09 11:43:26 -0800384 for (CfgNode *Node : reverse_range(Nodes)) {
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700385 if (NeedToProcess[Node->getIndex()]) {
386 NeedToProcess[Node->getIndex()] = false;
387 bool Changed = Node->liveness(getLiveness());
388 if (Changed) {
389 // If the beginning-of-block liveness changed since the last
390 // iteration, mark all in-edges as needing to be processed.
Jim Stichnothf44f3712014-10-01 14:05:51 -0700391 for (CfgNode *Pred : Node->getInEdges())
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700392 NeedToProcess[Pred->getIndex()] = true;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700393 }
394 }
395 }
396 }
397 if (Mode == Liveness_Intervals) {
398 // Reset each variable's live range.
Jim Stichnothf44f3712014-10-01 14:05:51 -0700399 for (Variable *Var : Variables)
400 Var->resetLiveRange();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700401 }
Jim Stichnothe5b73e62014-12-15 09:58:51 -0800402 // Make a final pass over each node to delete dead instructions,
403 // collect the first and last instruction numbers, and add live
404 // range segments for that node.
405 for (CfgNode *Node : Nodes) {
406 InstNumberT FirstInstNum = Inst::NumberSentinel;
407 InstNumberT LastInstNum = Inst::NumberSentinel;
Jim Stichnoth29841e82014-12-23 12:26:24 -0800408 for (Inst &I : Node->getPhis()) {
409 I.deleteIfDead();
410 if (Mode == Liveness_Intervals && !I.isDeleted()) {
Jim Stichnothe5b73e62014-12-15 09:58:51 -0800411 if (FirstInstNum == Inst::NumberSentinel)
Jim Stichnoth29841e82014-12-23 12:26:24 -0800412 FirstInstNum = I.getNumber();
413 assert(I.getNumber() > LastInstNum);
414 LastInstNum = I.getNumber();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700415 }
Jim Stichnothe5b73e62014-12-15 09:58:51 -0800416 }
Jim Stichnoth29841e82014-12-23 12:26:24 -0800417 for (Inst &I : Node->getInsts()) {
418 I.deleteIfDead();
419 if (Mode == Liveness_Intervals && !I.isDeleted()) {
Jim Stichnothe5b73e62014-12-15 09:58:51 -0800420 if (FirstInstNum == Inst::NumberSentinel)
Jim Stichnoth29841e82014-12-23 12:26:24 -0800421 FirstInstNum = I.getNumber();
422 assert(I.getNumber() > LastInstNum);
423 LastInstNum = I.getNumber();
Jim Stichnothe5b73e62014-12-15 09:58:51 -0800424 }
425 }
426 if (Mode == Liveness_Intervals) {
427 // Special treatment for live in-args. Their liveness needs to
428 // extend beyond the beginning of the function, otherwise an arg
429 // whose only use is in the first instruction will end up having
430 // the trivial live range [2,2) and will *not* interfere with
431 // other arguments. So if the first instruction of the method
432 // is "r=arg1+arg2", both args may be assigned the same
433 // register. This is accomplished by extending the entry
434 // block's instruction range from [2,n) to [1,n) which will
435 // transform the problematic [2,2) live ranges into [1,2).
436 if (FirstInstNum == Inst::NumberInitial)
437 FirstInstNum = Inst::NumberExtended;
438 Node->livenessAddIntervals(getLiveness(), FirstInstNum, LastInstNum);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700439 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700440 }
441}
442
443// Traverse every Variable of every Inst and verify that it
444// appears within the Variable's computed live range.
445bool Cfg::validateLiveness() const {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700446 TimerMarker T(TimerStack::TT_validateLiveness, this);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700447 bool Valid = true;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800448 OstreamLocker L(Ctx);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700449 Ostream &Str = Ctx->getStrDump();
Jim Stichnothf44f3712014-10-01 14:05:51 -0700450 for (CfgNode *Node : Nodes) {
Jim Stichnothae953202014-12-20 06:17:49 -0800451 Inst *FirstInst = nullptr;
Jim Stichnoth29841e82014-12-23 12:26:24 -0800452 for (Inst &Inst : Node->getInsts()) {
453 if (Inst.isDeleted())
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700454 continue;
Jim Stichnothae953202014-12-20 06:17:49 -0800455 if (FirstInst == nullptr)
Jim Stichnoth29841e82014-12-23 12:26:24 -0800456 FirstInst = &Inst;
457 InstNumberT InstNumber = Inst.getNumber();
458 if (Variable *Dest = Inst.getDest()) {
Jim Stichnoth47752552014-10-13 17:15:08 -0700459 if (!Dest->getIgnoreLiveness()) {
460 bool Invalid = false;
461 const bool IsDest = true;
462 if (!Dest->getLiveRange().containsValue(InstNumber, IsDest))
463 Invalid = true;
464 // Check that this instruction actually *begins* Dest's live
465 // range, by checking that Dest is not live in the previous
466 // instruction. As a special exception, we don't check this
467 // for the first instruction of the block, because a Phi
468 // temporary may be live at the end of the previous block,
469 // and if it is also assigned in the first instruction of
470 // this block, the adjacent live ranges get merged.
Jim Stichnoth29841e82014-12-23 12:26:24 -0800471 if (static_cast<class Inst *>(&Inst) != FirstInst &&
472 !Inst.isDestNonKillable() &&
Jim Stichnoth47752552014-10-13 17:15:08 -0700473 Dest->getLiveRange().containsValue(InstNumber - 1, IsDest))
474 Invalid = true;
475 if (Invalid) {
476 Valid = false;
Jim Stichnoth29841e82014-12-23 12:26:24 -0800477 Str << "Liveness error: inst " << Inst.getNumber() << " dest ";
Jim Stichnoth47752552014-10-13 17:15:08 -0700478 Dest->dump(this);
479 Str << " live range " << Dest->getLiveRange() << "\n";
480 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700481 }
482 }
Jim Stichnoth29841e82014-12-23 12:26:24 -0800483 for (SizeT I = 0; I < Inst.getSrcSize(); ++I) {
484 Operand *Src = Inst.getSrc(I);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700485 SizeT NumVars = Src->getNumVars();
486 for (SizeT J = 0; J < NumVars; ++J) {
487 const Variable *Var = Src->getVar(J);
Jim Stichnoth47752552014-10-13 17:15:08 -0700488 const bool IsDest = false;
489 if (!Var->getIgnoreLiveness() &&
490 !Var->getLiveRange().containsValue(InstNumber, IsDest)) {
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700491 Valid = false;
Jim Stichnoth29841e82014-12-23 12:26:24 -0800492 Str << "Liveness error: inst " << Inst.getNumber() << " var ";
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700493 Var->dump(this);
494 Str << " live range " << Var->getLiveRange() << "\n";
495 }
496 }
497 }
498 }
499 }
500 return Valid;
501}
502
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700503void Cfg::contractEmptyNodes() {
Jim Stichnoth3d44fe82014-11-01 10:10:18 -0700504 // If we're decorating the asm output with register liveness info,
505 // this information may become corrupted or incorrect after
506 // contracting nodes that contain only redundant assignments. As
507 // such, we disable this pass when DecorateAsm is specified. This
508 // may make the resulting code look more branchy, but it should have
509 // no effect on the register assignments.
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800510 if (Ctx->getFlags().getDecorateAsm())
Jim Stichnoth3d44fe82014-11-01 10:10:18 -0700511 return;
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700512 for (CfgNode *Node : Nodes) {
513 Node->contractIfEmpty();
514 }
515}
516
Jim Stichnothff9c7062014-09-18 04:50:49 -0700517void Cfg::doBranchOpt() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700518 TimerMarker T(TimerStack::TT_doBranchOpt, this);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700519 for (auto I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
520 auto NextNode = I;
Jim Stichnothff9c7062014-09-18 04:50:49 -0700521 ++NextNode;
Jim Stichnothae953202014-12-20 06:17:49 -0800522 (*I)->doBranchOpt(NextNode == E ? nullptr : *NextNode);
Jim Stichnothff9c7062014-09-18 04:50:49 -0700523 }
524}
525
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700526// ======================== Dump routines ======================== //
527
Jim Stichnothbbca7542015-02-11 16:08:31 -0800528// emitTextHeader() is not target-specific (apart from what is
529// abstracted by the Assembler), so it is defined here rather than in
530// the target lowering class.
531void Cfg::emitTextHeader(const IceString &MangledName, GlobalContext *Ctx,
532 const Assembler *Asm) {
Jim Stichnoth729dbd02015-02-25 14:48:43 -0800533 if (!ALLOW_DUMP)
534 return;
Jan Voung0faec4c2014-11-05 17:29:56 -0800535 Ostream &Str = Ctx->getStrEmit();
536 Str << "\t.text\n";
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800537 if (Ctx->getFlags().getFunctionSections())
Jan Voung0faec4c2014-11-05 17:29:56 -0800538 Str << "\t.section\t.text." << MangledName << ",\"ax\",@progbits\n";
Jim Stichnothbbca7542015-02-11 16:08:31 -0800539 if (!Asm->getInternal() || Ctx->getFlags().getDisableInternal()) {
Jan Voung0faec4c2014-11-05 17:29:56 -0800540 Str << "\t.globl\t" << MangledName << "\n";
Jan Voungb2d50842015-05-12 09:53:50 -0700541 Str << "\t.type\t" << MangledName << ",%function\n";
Jan Voung0faec4c2014-11-05 17:29:56 -0800542 }
Jan Voungb2d50842015-05-12 09:53:50 -0700543 Str << "\t" << Asm->getNonExecPadDirective() << " "
544 << Asm->getBundleAlignLog2Bytes() << ",0x";
Jan Voung08c3bcd2014-12-01 17:55:16 -0800545 for (uint8_t I : Asm->getNonExecBundlePadding())
Jan Voung0faec4c2014-11-05 17:29:56 -0800546 Str.write_hex(I);
547 Str << "\n";
548 Str << MangledName << ":\n";
549}
550
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700551void Cfg::emit() {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800552 if (!ALLOW_DUMP)
553 return;
Jim Stichnoth8363a062014-10-07 10:02:38 -0700554 TimerMarker T(TimerStack::TT_emit, this);
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800555 if (Ctx->getFlags().getDecorateAsm()) {
Jim Stichnoth3d44fe82014-11-01 10:10:18 -0700556 renumberInstructions();
557 getVMetadata()->init(VMK_Uses);
558 liveness(Liveness_Basic);
559 dump("After recomputing liveness for -decorate-asm");
560 }
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800561 OstreamLocker L(Ctx);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700562 Ostream &Str = Ctx->getStrEmit();
Jim Stichnoth989a7032014-08-08 10:13:44 -0700563 IceString MangledName = getContext()->mangleName(getFunctionName());
Jim Stichnothbbca7542015-02-11 16:08:31 -0800564 emitTextHeader(MangledName, Ctx, getAssembler<>());
Jim Stichnothf44f3712014-10-01 14:05:51 -0700565 for (CfgNode *Node : Nodes)
566 Node->emit(this);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700567 Str << "\n";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700568}
569
Jan Voung0faec4c2014-11-05 17:29:56 -0800570void Cfg::emitIAS() {
571 TimerMarker T(TimerStack::TT_emit, this);
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800572 // The emitIAS() routines emit into the internal assembler buffer,
Jim Stichnothbbca7542015-02-11 16:08:31 -0800573 // so there's no need to lock the streams.
Jan Voung0faec4c2014-11-05 17:29:56 -0800574 for (CfgNode *Node : Nodes)
575 Node->emitIAS(this);
Jan Voung0faec4c2014-11-05 17:29:56 -0800576}
577
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700578// Dumps the IR with an optional introductory message.
579void Cfg::dump(const IceString &Message) {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800580 if (!ALLOW_DUMP)
581 return;
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800582 if (!isVerbose())
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700583 return;
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800584 OstreamLocker L(Ctx);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700585 Ostream &Str = Ctx->getStrDump();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700586 if (!Message.empty())
587 Str << "================ " << Message << " ================\n";
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700588 setCurrentNode(getEntryNode());
589 // Print function name+args
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800590 if (isVerbose(IceV_Instructions)) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700591 Str << "define ";
Karl Schimpfdf80eb82015-02-09 14:20:22 -0800592 if (getInternal() && !Ctx->getFlags().getDisableInternal())
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700593 Str << "internal ";
Karl Schimpfdf6f9d12014-10-20 14:09:00 -0700594 Str << ReturnType << " @" << Ctx->mangleName(getFunctionName()) << "(";
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700595 for (SizeT i = 0; i < Args.size(); ++i) {
596 if (i > 0)
597 Str << ", ";
598 Str << Args[i]->getType() << " ";
599 Args[i]->dump(this);
600 }
601 Str << ") {\n";
602 }
Jim Stichnoth800dab22014-09-20 12:25:02 -0700603 resetCurrentNode();
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800604 if (isVerbose(IceV_Liveness)) {
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700605 // Print summary info about variables
Jim Stichnothf44f3712014-10-01 14:05:51 -0700606 for (Variable *Var : Variables) {
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700607 Str << "// multiblock=";
608 if (getVMetadata()->isTracked(Var))
609 Str << getVMetadata()->isMultiBlock(Var);
610 else
611 Str << "?";
612 Str << " weight=" << Var->getWeight() << " ";
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700613 Var->dump(this);
614 Str << " LIVE=" << Var->getLiveRange() << "\n";
615 }
616 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700617 // Print each basic block
Jim Stichnothf44f3712014-10-01 14:05:51 -0700618 for (CfgNode *Node : Nodes)
619 Node->dump(this);
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800620 if (isVerbose(IceV_Instructions))
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700621 Str << "}\n";
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700622}
623
624} // end of namespace Ice