Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4358 Serge 1
/*
2
 * Copyright 2011 Christoph Bumiller
3
 *
4
 * Permission is hereby granted, free of charge, to any person obtaining a
5
 * copy of this software and associated documentation files (the "Software"),
6
 * to deal in the Software without restriction, including without limitation
7
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
 * and/or sell copies of the Software, and to permit persons to whom the
9
 * Software is furnished to do so, subject to the following conditions:
10
 *
11
 * The above copyright notice and this permission notice shall be included in
12
 * all copies or substantial portions of the Software.
13
 *
14
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20
 * OTHER DEALINGS IN THE SOFTWARE.
21
 */
22
 
23
#include "nv50_ir.h"
24
 
25
namespace nv50_ir {
26
 
27
Function::Function(Program *p, const char *fnName, uint32_t label)
28
   : call(this),
29
     label(label),
30
     name(fnName),
31
     prog(p)
32
{
33
   cfgExit = NULL;
34
   domTree = NULL;
35
 
36
   bbArray = NULL;
37
   bbCount = 0;
38
   loopNestingBound = 0;
39
   regClobberMax = 0;
40
 
41
   binPos = 0;
42
   binSize = 0;
43
 
44
   stackPtr = NULL;
45
   tlsBase = 0;
46
   tlsSize = 0;
47
 
48
   prog->add(this, id);
49
}
50
 
51
Function::~Function()
52
{
53
   prog->del(this, id);
54
 
55
   if (domTree)
56
      delete domTree;
57
   if (bbArray)
58
      delete[] bbArray;
59
 
60
   // clear value refs and defs
61
   ins.clear();
62
   outs.clear();
63
 
64
   for (ArrayList::Iterator it = allInsns.iterator(); !it.end(); it.next())
65
      delete_Instruction(prog, reinterpret_cast(it.get()));
66
 
67
   for (ArrayList::Iterator it = allLValues.iterator(); !it.end(); it.next())
68
      delete_Value(prog, reinterpret_cast(it.get()));
69
 
70
   for (ArrayList::Iterator BBs = allBBlocks.iterator(); !BBs.end(); BBs.next())
71
      delete reinterpret_cast(BBs.get());
72
}
73
 
74
BasicBlock::BasicBlock(Function *fn) : cfg(this), dom(this), func(fn)
75
{
76
   program = func->getProgram();
77
 
78
   joinAt = phi = entry = exit = NULL;
79
 
80
   numInsns = 0;
81
   binPos = 0;
82
   binSize = 0;
83
 
84
   explicitCont = false;
85
 
86
   func->add(this, this->id);
87
}
88
 
89
BasicBlock::~BasicBlock()
90
{
91
   // nothing yet
92
}
93
 
94
BasicBlock *
95
BasicBlock::clone(ClonePolicy& pol) const
96
{
97
   BasicBlock *bb = new BasicBlock(pol.context());
98
 
99
   pol.set(this, bb);
100
 
101
   for (Instruction *i = getFirst(); i; i = i->next)
102
      bb->insertTail(i->clone(pol));
103
 
104
   pol.context()->cfg.insert(&bb->cfg);
105
 
106
   for (Graph::EdgeIterator it = cfg.outgoing(); !it.end(); it.next()) {
107
      BasicBlock *obb = BasicBlock::get(it.getNode());
108
      bb->cfg.attach(&pol.get(obb)->cfg, it.getType());
109
   }
110
 
111
   return bb;
112
}
113
 
114
BasicBlock *
115
BasicBlock::idom() const
116
{
117
   Graph::Node *dn = dom.parent();
118
   return dn ? BasicBlock::get(dn) : NULL;
119
}
120
 
121
void
122
BasicBlock::insertHead(Instruction *inst)
123
{
124
   assert(inst->next == 0 && inst->prev == 0);
125
 
126
   if (inst->op == OP_PHI) {
127
      if (phi) {
128
         insertBefore(phi, inst);
129
      } else {
130
         if (entry) {
131
            insertBefore(entry, inst);
132
         } else {
133
            assert(!exit);
134
            phi = exit = inst;
135
            inst->bb = this;
136
            ++numInsns;
137
         }
138
      }
139
   } else {
140
      if (entry) {
141
         insertBefore(entry, inst);
142
      } else {
143
         if (phi) {
144
            insertAfter(exit, inst); // after last phi
145
         } else {
146
            assert(!exit);
147
            entry = exit = inst;
148
            inst->bb = this;
149
            ++numInsns;
150
         }
151
      }
152
   }
153
}
154
 
155
void
156
BasicBlock::insertTail(Instruction *inst)
157
{
158
   assert(inst->next == 0 && inst->prev == 0);
159
 
160
   if (inst->op == OP_PHI) {
161
      if (entry) {
162
         insertBefore(entry, inst);
163
      } else
164
      if (exit) {
165
         assert(phi);
166
         insertAfter(exit, inst);
167
      } else {
168
         assert(!phi);
169
         phi = exit = inst;
170
         inst->bb = this;
171
         ++numInsns;
172
      }
173
   } else {
174
      if (exit) {
175
         insertAfter(exit, inst);
176
      } else {
177
         assert(!phi);
178
         entry = exit = inst;
179
         inst->bb = this;
180
         ++numInsns;
181
      }
182
   }
183
}
184
 
185
void
186
BasicBlock::insertBefore(Instruction *q, Instruction *p)
187
{
188
   assert(p && q);
189
 
190
   assert(p->next == 0 && p->prev == 0);
191
 
192
   if (q == entry) {
193
      if (p->op == OP_PHI) {
194
         if (!phi)
195
            phi = p;
196
      } else {
197
         entry = p;
198
      }
199
   } else
200
   if (q == phi) {
201
      assert(p->op == OP_PHI);
202
      phi = p;
203
   }
204
 
205
   p->next = q;
206
   p->prev = q->prev;
207
   if (p->prev)
208
      p->prev->next = p;
209
   q->prev = p;
210
 
211
   p->bb = this;
212
   ++numInsns;
213
}
214
 
215
void
216
BasicBlock::insertAfter(Instruction *p, Instruction *q)
217
{
218
   assert(p && q);
219
   assert(q->op != OP_PHI || p->op == OP_PHI);
220
 
221
   assert(q->next == 0 && q->prev == 0);
222
 
223
   if (p == exit)
224
      exit = q;
225
   if (p->op == OP_PHI && q->op != OP_PHI)
226
      entry = q;
227
 
228
   q->prev = p;
229
   q->next = p->next;
230
   if (q->next)
231
      q->next->prev = q;
232
   p->next = q;
233
 
234
   q->bb = this;
235
   ++numInsns;
236
}
237
 
238
void
239
BasicBlock::remove(Instruction *insn)
240
{
241
   assert(insn->bb == this);
242
 
243
   if (insn->prev)
244
      insn->prev->next = insn->next;
245
 
246
   if (insn->next)
247
      insn->next->prev = insn->prev;
248
   else
249
      exit = insn->prev;
250
 
251
   if (insn == entry) {
252
      if (insn->next)
253
         entry = insn->next;
254
      else
255
      if (insn->prev && insn->prev->op != OP_PHI)
256
         entry = insn->prev;
257
      else
258
         entry = NULL;
259
   }
260
 
261
   if (insn == phi)
262
      phi = (insn->next && insn->next->op == OP_PHI) ? insn->next : 0;
263
 
264
   --numInsns;
265
   insn->bb = NULL;
266
   insn->next =
267
   insn->prev = NULL;
268
}
269
 
270
void BasicBlock::permuteAdjacent(Instruction *a, Instruction *b)
271
{
272
   assert(a->bb == b->bb);
273
 
274
   if (a->next != b) {
275
      Instruction *i = a;
276
      a = b;
277
      b = i;
278
   }
279
   assert(a->next == b);
280
   assert(a->op != OP_PHI && b->op != OP_PHI);
281
 
282
   if (b == exit)
283
      exit = a;
284
   if (a == entry)
285
      entry = b;
286
 
287
   b->prev = a->prev;
288
   a->next = b->next;
289
   b->next = a;
290
   a->prev = b;
291
 
292
   if (b->prev)
293
      b->prev->next = b;
294
   if (a->prev)
295
      a->next->prev = a;
296
}
297
 
298
void
299
BasicBlock::splitCommon(Instruction *insn, BasicBlock *bb, bool attach)
300
{
301
   bb->entry = insn;
302
 
303
   if (insn) {
304
      exit = insn->prev;
305
      insn->prev = NULL;
306
   }
307
 
308
   if (exit)
309
      exit->next = NULL;
310
   else
311
      entry = NULL;
312
 
313
   while (!cfg.outgoing(true).end()) {
314
      Graph::Edge *e = cfg.outgoing(true).getEdge();
315
      bb->cfg.attach(e->getTarget(), e->getType());
316
      this->cfg.detach(e->getTarget());
317
   }
318
 
319
   for (; insn; insn = insn->next) {
320
      this->numInsns--;
321
      bb->numInsns++;
322
      insn->bb = bb;
323
      bb->exit = insn;
324
   }
325
   if (attach)
326
      this->cfg.attach(&bb->cfg, Graph::Edge::TREE);
327
}
328
 
329
BasicBlock *
330
BasicBlock::splitBefore(Instruction *insn, bool attach)
331
{
332
   BasicBlock *bb = new BasicBlock(func);
333
   assert(!insn || insn->op != OP_PHI);
334
 
335
   splitCommon(insn, bb, attach);
336
   return bb;
337
}
338
 
339
BasicBlock *
340
BasicBlock::splitAfter(Instruction *insn, bool attach)
341
{
342
   BasicBlock *bb = new BasicBlock(func);
343
   assert(!insn || insn->op != OP_PHI);
344
 
345
   bb->joinAt = joinAt;
346
   joinAt = NULL;
347
 
348
   splitCommon(insn ? insn->next : NULL, bb, attach);
349
   return bb;
350
}
351
 
352
bool
353
BasicBlock::dominatedBy(BasicBlock *that)
354
{
355
   Graph::Node *bn = &that->dom;
356
   Graph::Node *dn = &this->dom;
357
 
358
   while (dn && dn != bn)
359
      dn = dn->parent();
360
 
361
   return dn != NULL;
362
}
363
 
364
unsigned int
365
BasicBlock::initiatesSimpleConditional() const
366
{
367
   Graph::Node *out[2];
368
   int n;
369
   Graph::Edge::Type eR;
370
 
371
   if (cfg.outgoingCount() != 2) // -> if and -> else/endif
372
      return false;
373
 
374
   n = 0;
375
   for (Graph::EdgeIterator ei = cfg.outgoing(); !ei.end(); ei.next())
376
      out[n++] = ei.getNode();
377
   eR = out[1]->outgoing().getType();
378
 
379
   // IF block is out edge to the right
380
   if (eR == Graph::Edge::CROSS || eR == Graph::Edge::BACK)
381
      return 0x2;
382
 
383
   if (out[1]->outgoingCount() != 1) // 0 is IF { RET; }, >1 is more divergence
384
      return 0x0;
385
   // do they reconverge immediately ?
386
   if (out[1]->outgoing().getNode() == out[0])
387
      return 0x1;
388
   if (out[0]->outgoingCount() == 1)
389
      if (out[0]->outgoing().getNode() == out[1]->outgoing().getNode())
390
         return 0x3;
391
 
392
   return 0x0;
393
}
394
 
395
bool
396
Function::setEntry(BasicBlock *bb)
397
{
398
   if (cfg.getRoot())
399
      return false;
400
   cfg.insert(&bb->cfg);
401
   return true;
402
}
403
 
404
bool
405
Function::setExit(BasicBlock *bb)
406
{
407
   if (cfgExit)
408
      return false;
409
   cfgExit = &bb->cfg;
410
   return true;
411
}
412
 
413
unsigned int
414
Function::orderInstructions(ArrayList &result)
415
{
416
   result.clear();
417
 
418
   for (IteratorRef it = cfg.iteratorCFG(); !it->end(); it->next()) {
419
      BasicBlock *bb =
420
         BasicBlock::get(reinterpret_cast(it->get()));
421
 
422
      for (Instruction *insn = bb->getFirst(); insn; insn = insn->next)
423
         result.insert(insn, insn->serial);
424
   }
425
 
426
   return result.getSize();
427
}
428
 
429
void
430
Function::buildLiveSets()
431
{
432
   for (unsigned i = 0; i <= loopNestingBound; ++i)
433
      buildLiveSetsPreSSA(BasicBlock::get(cfg.getRoot()), cfg.nextSequence());
434
 
435
   for (ArrayList::Iterator bi = allBBlocks.iterator(); !bi.end(); bi.next())
436
      BasicBlock::get(bi)->liveSet.marker = false;
437
}
438
 
439
void
440
Function::buildDefSets()
441
{
442
   for (unsigned i = 0; i <= loopNestingBound; ++i)
443
      buildDefSetsPreSSA(BasicBlock::get(cfgExit), cfg.nextSequence());
444
 
445
   for (ArrayList::Iterator bi = allBBlocks.iterator(); !bi.end(); bi.next())
446
      BasicBlock::get(bi)->liveSet.marker = false;
447
}
448
 
449
bool
450
Pass::run(Program *prog, bool ordered, bool skipPhi)
451
{
452
   this->prog = prog;
453
   err = false;
454
   return doRun(prog, ordered, skipPhi);
455
}
456
 
457
bool
458
Pass::doRun(Program *prog, bool ordered, bool skipPhi)
459
{
460
   for (IteratorRef it = prog->calls.iteratorDFS(false);
461
        !it->end(); it->next()) {
462
      Graph::Node *n = reinterpret_cast(it->get());
463
      if (!doRun(Function::get(n), ordered, skipPhi))
464
         return false;
465
   }
466
   return !err;
467
}
468
 
469
bool
470
Pass::run(Function *func, bool ordered, bool skipPhi)
471
{
472
   prog = func->getProgram();
473
   err = false;
474
   return doRun(func, ordered, skipPhi);
475
}
476
 
477
bool
478
Pass::doRun(Function *func, bool ordered, bool skipPhi)
479
{
480
   IteratorRef bbIter;
481
   BasicBlock *bb;
482
   Instruction *insn, *next;
483
 
484
   this->func = func;
485
   if (!visit(func))
486
      return false;
487
 
488
   bbIter = ordered ? func->cfg.iteratorCFG() : func->cfg.iteratorDFS();
489
 
490
   for (; !bbIter->end(); bbIter->next()) {
491
      bb = BasicBlock::get(reinterpret_cast(bbIter->get()));
492
      if (!visit(bb))
493
         break;
494
      for (insn = skipPhi ? bb->getEntry() : bb->getFirst(); insn != NULL;
495
           insn = next) {
496
         next = insn->next;
497
         if (!visit(insn))
498
            break;
499
      }
500
   }
501
 
502
   return !err;
503
}
504
 
505
void
506
Function::printCFGraph(const char *filePath)
507
{
508
   FILE *out = fopen(filePath, "a");
509
   if (!out) {
510
      ERROR("failed to open file: %s\n", filePath);
511
      return;
512
   }
513
   INFO("printing control flow graph to: %s\n", filePath);
514
 
515
   fprintf(out, "digraph G {\n");
516
 
517
   for (IteratorRef it = cfg.iteratorDFS(); !it->end(); it->next()) {
518
      BasicBlock *bb = BasicBlock::get(
519
         reinterpret_cast(it->get()));
520
      int idA = bb->getId();
521
      for (Graph::EdgeIterator ei = bb->cfg.outgoing(); !ei.end(); ei.next()) {
522
         int idB = BasicBlock::get(ei.getNode())->getId();
523
         switch (ei.getType()) {
524
         case Graph::Edge::TREE:
525
            fprintf(out, "\t%i -> %i;\n", idA, idB);
526
            break;
527
         case Graph::Edge::FORWARD:
528
            fprintf(out, "\t%i -> %i [color=green];\n", idA, idB);
529
            break;
530
         case Graph::Edge::CROSS:
531
            fprintf(out, "\t%i -> %i [color=red];\n", idA, idB);
532
            break;
533
         case Graph::Edge::BACK:
534
            fprintf(out, "\t%i -> %i;\n", idA, idB);
535
            break;
536
         case Graph::Edge::DUMMY:
537
            fprintf(out, "\t%i -> %i [style=dotted];\n", idA, idB);
538
            break;
539
         default:
540
            assert(0);
541
            break;
542
         }
543
      }
544
   }
545
 
546
   fprintf(out, "}\n");
547
   fclose(out);
548
}
549
 
550
} // namespace nv50_ir