blob: e8c74bacc3a08c3e44c460092ed950edfea76395 [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
Jan Voungec270732015-01-12 17:00:22 -080015#include "assembler.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"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070021#include "IceInst.h"
Jim Stichnothd97c7df2014-06-04 11:57:08 -070022#include "IceLiveness.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070023#include "IceOperand.h"
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070024#include "IceTargetLowering.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070025
26namespace Ice {
27
Jim Stichnothae953202014-12-20 06:17:49 -080028thread_local const Cfg *Cfg::CurrentCfg = nullptr;
Jim Stichnoth31c95592014-12-19 12:51:35 -080029
Jan Voung1d62cf02015-01-09 14:57:32 -080030ArenaAllocator<> *getCurrentCfgAllocator() {
Jim Stichnoth31c95592014-12-19 12:51:35 -080031 return Cfg::getCurrentCfgAllocator();
32}
33
Jim Stichnothf7c9a142014-04-29 10:52:43 -070034Cfg::Cfg(GlobalContext *Ctx)
35 : Ctx(Ctx), FunctionName(""), ReturnType(IceType_void),
Jim Stichnoth8363a062014-10-07 10:02:38 -070036 IsInternalLinkage(false), HasError(false), FocusedTiming(false),
Jim Stichnothae953202014-12-20 06:17:49 -080037 ErrorMessage(""), Entry(nullptr), NextInstNumber(Inst::NumberInitial),
Jan Voung1d62cf02015-01-09 14:57:32 -080038 Allocator(new ArenaAllocator<>()), Live(nullptr),
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070039 Target(TargetLowering::createLowering(Ctx->getTargetArch(), this)),
Jan Voung8acded02014-09-22 18:02:25 -070040 VMetadata(new VariablesMetadata(this)),
41 TargetAssembler(
42 TargetLowering::createAssembler(Ctx->getTargetArch(), this)),
Jim Stichnothae953202014-12-20 06:17:49 -080043 CurrentNode(nullptr) {
Karl Schimpf6fcbddd2014-11-06 09:49:24 -080044 assert(!Ctx->isIRGenerationDisabled() &&
45 "Attempt to build cfg when IR generation disabled");
46}
Jim Stichnothf7c9a142014-04-29 10:52:43 -070047
Jim Stichnoth31c95592014-12-19 12:51:35 -080048Cfg::~Cfg() {
Jim Stichnothae953202014-12-20 06:17:49 -080049 // TODO(stichnot,kschimpf): Set CurrentCfg=nullptr in the dtor for
Jim Stichnoth31c95592014-12-19 12:51:35 -080050 // safety. This can't be done currently because the translator
51 // manages the Cfg by creating a new Cfg (which sets CurrentCfg to
52 // the new value), then deleting the old Cfg (which would then reset
Jim Stichnothae953202014-12-20 06:17:49 -080053 // CurrentCfg to nullptr).
Jim Stichnoth31c95592014-12-19 12:51:35 -080054}
Jim Stichnothf7c9a142014-04-29 10:52:43 -070055
56void Cfg::setError(const IceString &Message) {
57 HasError = true;
58 ErrorMessage = Message;
59 Ctx->getStrDump() << "ICE translation error: " << ErrorMessage << "\n";
60}
61
Jim Stichnoth668a7a32014-12-10 15:32:25 -080062CfgNode *Cfg::makeNode() {
Jim Stichnothf7c9a142014-04-29 10:52:43 -070063 SizeT LabelIndex = Nodes.size();
Jim Stichnoth668a7a32014-12-10 15:32:25 -080064 CfgNode *Node = CfgNode::create(this, LabelIndex);
Jim Stichnothf7c9a142014-04-29 10:52:43 -070065 Nodes.push_back(Node);
66 return Node;
67}
68
Jim Stichnothf7c9a142014-04-29 10:52:43 -070069void Cfg::addArg(Variable *Arg) {
Jim Stichnoth144cdce2014-09-22 16:02:59 -070070 Arg->setIsArg();
Jim Stichnothf7c9a142014-04-29 10:52:43 -070071 Args.push_back(Arg);
72}
73
Jim Stichnoth144cdce2014-09-22 16:02:59 -070074void Cfg::addImplicitArg(Variable *Arg) {
75 Arg->setIsImplicitArg();
76 ImplicitArgs.push_back(Arg);
77}
78
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070079// Returns whether the stack frame layout has been computed yet. This
80// is used for dumping the stack frame location of Variables.
81bool Cfg::hasComputedFrame() const { return getTarget()->hasComputedFrame(); }
82
83void Cfg::translate() {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070084 if (hasError())
85 return;
Jim Stichnoth1c44d812014-12-08 14:57:52 -080086 if (ALLOW_DUMP) {
87 const IceString &TimingFocusOn = getContext()->getFlags().TimingFocusOn;
88 if (TimingFocusOn == "*" || TimingFocusOn == getFunctionName()) {
89 setFocusedTiming();
90 getContext()->resetTimer(GlobalContext::TSK_Default);
91 getContext()->setTimerName(GlobalContext::TSK_Default, getFunctionName());
92 }
Jim Stichnothd14b1a02014-10-08 08:28:36 -070093 }
Jim Stichnoth8363a062014-10-07 10:02:38 -070094 TimerMarker T(TimerStack::TT_translate, this);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070095
Jim Stichnothd97c7df2014-06-04 11:57:08 -070096 dump("Initial CFG");
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070097
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070098 // The set of translation passes and their order are determined by
99 // the target.
100 getTarget()->translate();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700101
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700102 dump("Final output");
Jim Stichnoth8363a062014-10-07 10:02:38 -0700103 if (getFocusedTiming())
104 getContext()->dumpTimers();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700105}
106
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700107void Cfg::computePredecessors() {
Jim Stichnothf44f3712014-10-01 14:05:51 -0700108 for (CfgNode *Node : Nodes)
109 Node->computePredecessors();
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700110}
111
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700112void Cfg::renumberInstructions() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700113 TimerMarker T(TimerStack::TT_renumberInstructions, this);
Jim Stichnothe5b73e62014-12-15 09:58:51 -0800114 NextInstNumber = Inst::NumberInitial;
Jim Stichnothf44f3712014-10-01 14:05:51 -0700115 for (CfgNode *Node : Nodes)
116 Node->renumberInstructions();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700117}
118
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700119// placePhiLoads() must be called before placePhiStores().
120void Cfg::placePhiLoads() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700121 TimerMarker T(TimerStack::TT_placePhiLoads, this);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700122 for (CfgNode *Node : Nodes)
123 Node->placePhiLoads();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700124}
125
126// placePhiStores() must be called after placePhiLoads().
127void Cfg::placePhiStores() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700128 TimerMarker T(TimerStack::TT_placePhiStores, this);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700129 for (CfgNode *Node : Nodes)
130 Node->placePhiStores();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700131}
132
133void Cfg::deletePhis() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700134 TimerMarker T(TimerStack::TT_deletePhis, this);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700135 for (CfgNode *Node : Nodes)
136 Node->deletePhis();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700137}
138
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700139void Cfg::advancedPhiLowering() {
140 TimerMarker T(TimerStack::TT_advancedPhiLowering, this);
141 // This splits edges and appends new nodes to the end of the node
142 // list. This can invalidate iterators, so don't use an iterator.
143 SizeT NumNodes = getNumNodes();
144 for (SizeT I = 0; I < NumNodes; ++I)
145 Nodes[I]->advancedPhiLowering();
146}
147
148// Find a reasonable placement for nodes that have not yet been
149// placed, while maintaining the same relative ordering among already
150// placed nodes.
151void Cfg::reorderNodes() {
152 typedef std::list<CfgNode *> PlacedList;
153 PlacedList Placed; // Nodes with relative placement locked down
154 PlacedList Unreachable; // Unreachable nodes
155 PlacedList::iterator NoPlace = Placed.end();
156 // Keep track of where each node has been tentatively placed so that
157 // we can manage insertions into the middle.
158 std::vector<PlacedList::iterator> PlaceIndex(Nodes.size(), NoPlace);
159 for (CfgNode *Node : Nodes) {
160 // The "do ... while(0);" construct is to factor out the
161 // --PlaceIndex and assert() statements before moving to the next
162 // node.
163 do {
164 if (!Node->needsPlacement()) {
165 // Add to the end of the Placed list.
166 Placed.push_back(Node);
167 PlaceIndex[Node->getIndex()] = Placed.end();
168 continue;
169 }
170 Node->setNeedsPlacement(false);
Jim Stichnothbfb410d2014-11-05 16:04:05 -0800171 if (Node != getEntryNode() && Node->getInEdges().empty()) {
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700172 // The node has essentially been deleted since it is not a
173 // successor of any other node.
174 Unreachable.push_back(Node);
175 PlaceIndex[Node->getIndex()] = Unreachable.end();
176 continue;
177 }
178 // Assume for now that the unplaced node is from edge-splitting
179 // and therefore has 1 in-edge and 1 out-edge (actually, possibly
180 // more than 1 in-edge if the predecessor node was contracted).
181 // If this changes in the future, rethink the strategy.
182 assert(Node->getInEdges().size() >= 1);
183 assert(Node->getOutEdges().size() == 1);
184
185 // If it's a (non-critical) edge where the successor has a single
186 // in-edge, then place it before the successor.
Jim Stichnothbfb410d2014-11-05 16:04:05 -0800187 CfgNode *Succ = Node->getOutEdges().front();
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700188 if (Succ->getInEdges().size() == 1 &&
189 PlaceIndex[Succ->getIndex()] != NoPlace) {
190 Placed.insert(PlaceIndex[Succ->getIndex()], Node);
191 PlaceIndex[Node->getIndex()] = PlaceIndex[Succ->getIndex()];
192 continue;
193 }
194
195 // Otherwise, place it after the (first) predecessor.
Jim Stichnothbfb410d2014-11-05 16:04:05 -0800196 CfgNode *Pred = Node->getInEdges().front();
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700197 auto PredPosition = PlaceIndex[Pred->getIndex()];
198 // It shouldn't be the case that PredPosition==NoPlace, but if
199 // that somehow turns out to be true, we just insert Node before
200 // PredPosition=NoPlace=Placed.end() .
201 if (PredPosition != NoPlace)
202 ++PredPosition;
203 Placed.insert(PredPosition, Node);
204 PlaceIndex[Node->getIndex()] = PredPosition;
205 } while (0);
206
207 --PlaceIndex[Node->getIndex()];
208 assert(*PlaceIndex[Node->getIndex()] == Node);
209 }
210
211 // Reorder Nodes according to the built-up lists.
Jim Stichnothbfb410d2014-11-05 16:04:05 -0800212 SizeT OldSize = Nodes.size();
213 (void)OldSize;
214 Nodes.clear();
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700215 for (CfgNode *Node : Placed)
Jim Stichnothbfb410d2014-11-05 16:04:05 -0800216 Nodes.push_back(Node);
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700217 for (CfgNode *Node : Unreachable)
Jim Stichnothbfb410d2014-11-05 16:04:05 -0800218 Nodes.push_back(Node);
219 assert(Nodes.size() == OldSize);
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700220}
221
Matt Wala45a06232014-07-09 16:33:22 -0700222void Cfg::doArgLowering() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700223 TimerMarker T(TimerStack::TT_doArgLowering, this);
Matt Wala45a06232014-07-09 16:33:22 -0700224 getTarget()->lowerArguments();
225}
226
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700227void Cfg::doAddressOpt() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700228 TimerMarker T(TimerStack::TT_doAddressOpt, this);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700229 for (CfgNode *Node : Nodes)
230 Node->doAddressOpt();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700231}
232
Matt Walac3302742014-08-15 16:21:56 -0700233void Cfg::doNopInsertion() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700234 TimerMarker T(TimerStack::TT_doNopInsertion, this);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700235 for (CfgNode *Node : Nodes)
236 Node->doNopInsertion();
Matt Walac3302742014-08-15 16:21:56 -0700237}
238
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700239void Cfg::genCode() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700240 TimerMarker T(TimerStack::TT_genCode, this);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700241 for (CfgNode *Node : Nodes)
242 Node->genCode();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700243}
244
245// Compute the stack frame layout.
246void Cfg::genFrame() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700247 TimerMarker T(TimerStack::TT_genFrame, this);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700248 getTarget()->addProlog(Entry);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700249 for (CfgNode *Node : Nodes)
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700250 if (Node->getHasReturn())
251 getTarget()->addEpilog(Node);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700252}
253
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700254// This is a lightweight version of live-range-end calculation. Marks
255// the last use of only those variables whose definition and uses are
256// completely with a single block. It is a quick single pass and
257// doesn't need to iterate until convergence.
258void Cfg::livenessLightweight() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700259 TimerMarker T(TimerStack::TT_livenessLightweight, this);
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700260 getVMetadata()->init(VMK_Uses);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700261 for (CfgNode *Node : Nodes)
262 Node->livenessLightweight();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700263}
264
265void Cfg::liveness(LivenessMode Mode) {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700266 TimerMarker T(TimerStack::TT_liveness, this);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700267 Live.reset(new Liveness(this, Mode));
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700268 getVMetadata()->init(VMK_Uses);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700269 Live->init();
270 // Initialize with all nodes needing to be processed.
271 llvm::BitVector NeedToProcess(Nodes.size(), true);
272 while (NeedToProcess.any()) {
273 // Iterate in reverse topological order to speed up convergence.
Jim Stichnoth7e571362015-01-09 11:43:26 -0800274 for (CfgNode *Node : reverse_range(Nodes)) {
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700275 if (NeedToProcess[Node->getIndex()]) {
276 NeedToProcess[Node->getIndex()] = false;
277 bool Changed = Node->liveness(getLiveness());
278 if (Changed) {
279 // If the beginning-of-block liveness changed since the last
280 // iteration, mark all in-edges as needing to be processed.
Jim Stichnothf44f3712014-10-01 14:05:51 -0700281 for (CfgNode *Pred : Node->getInEdges())
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700282 NeedToProcess[Pred->getIndex()] = true;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700283 }
284 }
285 }
286 }
287 if (Mode == Liveness_Intervals) {
288 // Reset each variable's live range.
Jim Stichnothf44f3712014-10-01 14:05:51 -0700289 for (Variable *Var : Variables)
290 Var->resetLiveRange();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700291 }
Jim Stichnothe5b73e62014-12-15 09:58:51 -0800292 // Make a final pass over each node to delete dead instructions,
293 // collect the first and last instruction numbers, and add live
294 // range segments for that node.
295 for (CfgNode *Node : Nodes) {
296 InstNumberT FirstInstNum = Inst::NumberSentinel;
297 InstNumberT LastInstNum = Inst::NumberSentinel;
Jim Stichnoth29841e82014-12-23 12:26:24 -0800298 for (Inst &I : Node->getPhis()) {
299 I.deleteIfDead();
300 if (Mode == Liveness_Intervals && !I.isDeleted()) {
Jim Stichnothe5b73e62014-12-15 09:58:51 -0800301 if (FirstInstNum == Inst::NumberSentinel)
Jim Stichnoth29841e82014-12-23 12:26:24 -0800302 FirstInstNum = I.getNumber();
303 assert(I.getNumber() > LastInstNum);
304 LastInstNum = I.getNumber();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700305 }
Jim Stichnothe5b73e62014-12-15 09:58:51 -0800306 }
Jim Stichnoth29841e82014-12-23 12:26:24 -0800307 for (Inst &I : Node->getInsts()) {
308 I.deleteIfDead();
309 if (Mode == Liveness_Intervals && !I.isDeleted()) {
Jim Stichnothe5b73e62014-12-15 09:58:51 -0800310 if (FirstInstNum == Inst::NumberSentinel)
Jim Stichnoth29841e82014-12-23 12:26:24 -0800311 FirstInstNum = I.getNumber();
312 assert(I.getNumber() > LastInstNum);
313 LastInstNum = I.getNumber();
Jim Stichnothe5b73e62014-12-15 09:58:51 -0800314 }
315 }
316 if (Mode == Liveness_Intervals) {
317 // Special treatment for live in-args. Their liveness needs to
318 // extend beyond the beginning of the function, otherwise an arg
319 // whose only use is in the first instruction will end up having
320 // the trivial live range [2,2) and will *not* interfere with
321 // other arguments. So if the first instruction of the method
322 // is "r=arg1+arg2", both args may be assigned the same
323 // register. This is accomplished by extending the entry
324 // block's instruction range from [2,n) to [1,n) which will
325 // transform the problematic [2,2) live ranges into [1,2).
326 if (FirstInstNum == Inst::NumberInitial)
327 FirstInstNum = Inst::NumberExtended;
328 Node->livenessAddIntervals(getLiveness(), FirstInstNum, LastInstNum);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700329 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700330 }
331}
332
333// Traverse every Variable of every Inst and verify that it
334// appears within the Variable's computed live range.
335bool Cfg::validateLiveness() const {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700336 TimerMarker T(TimerStack::TT_validateLiveness, this);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700337 bool Valid = true;
338 Ostream &Str = Ctx->getStrDump();
Jim Stichnothf44f3712014-10-01 14:05:51 -0700339 for (CfgNode *Node : Nodes) {
Jim Stichnothae953202014-12-20 06:17:49 -0800340 Inst *FirstInst = nullptr;
Jim Stichnoth29841e82014-12-23 12:26:24 -0800341 for (Inst &Inst : Node->getInsts()) {
342 if (Inst.isDeleted())
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700343 continue;
Jim Stichnothae953202014-12-20 06:17:49 -0800344 if (FirstInst == nullptr)
Jim Stichnoth29841e82014-12-23 12:26:24 -0800345 FirstInst = &Inst;
346 InstNumberT InstNumber = Inst.getNumber();
347 if (Variable *Dest = Inst.getDest()) {
Jim Stichnoth47752552014-10-13 17:15:08 -0700348 if (!Dest->getIgnoreLiveness()) {
349 bool Invalid = false;
350 const bool IsDest = true;
351 if (!Dest->getLiveRange().containsValue(InstNumber, IsDest))
352 Invalid = true;
353 // Check that this instruction actually *begins* Dest's live
354 // range, by checking that Dest is not live in the previous
355 // instruction. As a special exception, we don't check this
356 // for the first instruction of the block, because a Phi
357 // temporary may be live at the end of the previous block,
358 // and if it is also assigned in the first instruction of
359 // this block, the adjacent live ranges get merged.
Jim Stichnoth29841e82014-12-23 12:26:24 -0800360 if (static_cast<class Inst *>(&Inst) != FirstInst &&
361 !Inst.isDestNonKillable() &&
Jim Stichnoth47752552014-10-13 17:15:08 -0700362 Dest->getLiveRange().containsValue(InstNumber - 1, IsDest))
363 Invalid = true;
364 if (Invalid) {
365 Valid = false;
Jim Stichnoth29841e82014-12-23 12:26:24 -0800366 Str << "Liveness error: inst " << Inst.getNumber() << " dest ";
Jim Stichnoth47752552014-10-13 17:15:08 -0700367 Dest->dump(this);
368 Str << " live range " << Dest->getLiveRange() << "\n";
369 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700370 }
371 }
Jim Stichnoth29841e82014-12-23 12:26:24 -0800372 for (SizeT I = 0; I < Inst.getSrcSize(); ++I) {
373 Operand *Src = Inst.getSrc(I);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700374 SizeT NumVars = Src->getNumVars();
375 for (SizeT J = 0; J < NumVars; ++J) {
376 const Variable *Var = Src->getVar(J);
Jim Stichnoth47752552014-10-13 17:15:08 -0700377 const bool IsDest = false;
378 if (!Var->getIgnoreLiveness() &&
379 !Var->getLiveRange().containsValue(InstNumber, IsDest)) {
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700380 Valid = false;
Jim Stichnoth29841e82014-12-23 12:26:24 -0800381 Str << "Liveness error: inst " << Inst.getNumber() << " var ";
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700382 Var->dump(this);
383 Str << " live range " << Var->getLiveRange() << "\n";
384 }
385 }
386 }
387 }
388 }
389 return Valid;
390}
391
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700392void Cfg::contractEmptyNodes() {
Jim Stichnoth3d44fe82014-11-01 10:10:18 -0700393 // If we're decorating the asm output with register liveness info,
394 // this information may become corrupted or incorrect after
395 // contracting nodes that contain only redundant assignments. As
396 // such, we disable this pass when DecorateAsm is specified. This
397 // may make the resulting code look more branchy, but it should have
398 // no effect on the register assignments.
399 if (Ctx->getFlags().DecorateAsm)
400 return;
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700401 for (CfgNode *Node : Nodes) {
402 Node->contractIfEmpty();
403 }
404}
405
Jim Stichnothff9c7062014-09-18 04:50:49 -0700406void Cfg::doBranchOpt() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700407 TimerMarker T(TimerStack::TT_doBranchOpt, this);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700408 for (auto I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
409 auto NextNode = I;
Jim Stichnothff9c7062014-09-18 04:50:49 -0700410 ++NextNode;
Jim Stichnothae953202014-12-20 06:17:49 -0800411 (*I)->doBranchOpt(NextNode == E ? nullptr : *NextNode);
Jim Stichnothff9c7062014-09-18 04:50:49 -0700412 }
413}
414
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700415// ======================== Dump routines ======================== //
416
Jan Voung0faec4c2014-11-05 17:29:56 -0800417void Cfg::emitTextHeader(const IceString &MangledName) {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800418 // Note: Still used by emit IAS.
Jan Voung0faec4c2014-11-05 17:29:56 -0800419 Ostream &Str = Ctx->getStrEmit();
420 Str << "\t.text\n";
421 if (Ctx->getFlags().FunctionSections)
422 Str << "\t.section\t.text." << MangledName << ",\"ax\",@progbits\n";
423 if (!getInternal() || Ctx->getFlags().DisableInternal) {
424 Str << "\t.globl\t" << MangledName << "\n";
425 Str << "\t.type\t" << MangledName << ",@function\n";
426 }
Jan Voung08c3bcd2014-12-01 17:55:16 -0800427 Assembler *Asm = getAssembler<Assembler>();
428 Str << "\t.p2align " << Asm->getBundleAlignLog2Bytes() << ",0x";
429 for (uint8_t I : Asm->getNonExecBundlePadding())
Jan Voung0faec4c2014-11-05 17:29:56 -0800430 Str.write_hex(I);
431 Str << "\n";
432 Str << MangledName << ":\n";
433}
434
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700435void Cfg::emit() {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800436 if (!ALLOW_DUMP)
437 return;
Jim Stichnoth8363a062014-10-07 10:02:38 -0700438 TimerMarker T(TimerStack::TT_emit, this);
Jim Stichnoth3d44fe82014-11-01 10:10:18 -0700439 if (Ctx->getFlags().DecorateAsm) {
440 renumberInstructions();
441 getVMetadata()->init(VMK_Uses);
442 liveness(Liveness_Basic);
443 dump("After recomputing liveness for -decorate-asm");
444 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700445 Ostream &Str = Ctx->getStrEmit();
Jim Stichnoth989a7032014-08-08 10:13:44 -0700446 IceString MangledName = getContext()->mangleName(getFunctionName());
Jan Voung0faec4c2014-11-05 17:29:56 -0800447 emitTextHeader(MangledName);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700448 for (CfgNode *Node : Nodes)
449 Node->emit(this);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700450 Str << "\n";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700451}
452
Jan Voung0faec4c2014-11-05 17:29:56 -0800453void Cfg::emitIAS() {
454 TimerMarker T(TimerStack::TT_emit, this);
455 assert(!Ctx->getFlags().DecorateAsm);
456 IceString MangledName = getContext()->mangleName(getFunctionName());
Jan Voung08c3bcd2014-12-01 17:55:16 -0800457 if (!Ctx->getFlags().UseELFWriter)
458 emitTextHeader(MangledName);
Jan Voung0faec4c2014-11-05 17:29:56 -0800459 for (CfgNode *Node : Nodes)
460 Node->emitIAS(this);
Jan Voung08c3bcd2014-12-01 17:55:16 -0800461 // Now write the function to the file and track.
462 if (Ctx->getFlags().UseELFWriter) {
463 getAssembler<Assembler>()->alignFunction();
Jan Voungec270732015-01-12 17:00:22 -0800464 Ctx->getObjectWriter()->writeFunctionCode(MangledName, getInternal(),
465 getAssembler<Assembler>());
Jan Voung08c3bcd2014-12-01 17:55:16 -0800466 } else {
467 getAssembler<Assembler>()->emitIASBytes(Ctx);
468 }
Jan Voung0faec4c2014-11-05 17:29:56 -0800469}
470
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700471// Dumps the IR with an optional introductory message.
472void Cfg::dump(const IceString &Message) {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800473 if (!ALLOW_DUMP)
474 return;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700475 if (!Ctx->isVerbose())
476 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700477 Ostream &Str = Ctx->getStrDump();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700478 if (!Message.empty())
479 Str << "================ " << Message << " ================\n";
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700480 setCurrentNode(getEntryNode());
481 // Print function name+args
482 if (getContext()->isVerbose(IceV_Instructions)) {
483 Str << "define ";
Jim Stichnoth088b2be2014-10-23 12:02:08 -0700484 if (getInternal() && !Ctx->getFlags().DisableInternal)
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700485 Str << "internal ";
Karl Schimpfdf6f9d12014-10-20 14:09:00 -0700486 Str << ReturnType << " @" << Ctx->mangleName(getFunctionName()) << "(";
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700487 for (SizeT i = 0; i < Args.size(); ++i) {
488 if (i > 0)
489 Str << ", ";
490 Str << Args[i]->getType() << " ";
491 Args[i]->dump(this);
492 }
493 Str << ") {\n";
494 }
Jim Stichnoth800dab22014-09-20 12:25:02 -0700495 resetCurrentNode();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700496 if (getContext()->isVerbose(IceV_Liveness)) {
497 // Print summary info about variables
Jim Stichnothf44f3712014-10-01 14:05:51 -0700498 for (Variable *Var : Variables) {
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700499 Str << "// multiblock=";
500 if (getVMetadata()->isTracked(Var))
501 Str << getVMetadata()->isMultiBlock(Var);
502 else
503 Str << "?";
504 Str << " weight=" << Var->getWeight() << " ";
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700505 Var->dump(this);
506 Str << " LIVE=" << Var->getLiveRange() << "\n";
507 }
508 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700509 // Print each basic block
Jim Stichnothf44f3712014-10-01 14:05:51 -0700510 for (CfgNode *Node : Nodes)
511 Node->dump(this);
512 if (getContext()->isVerbose(IceV_Instructions))
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700513 Str << "}\n";
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700514}
515
516} // end of namespace Ice