Home | History | Annotate | Download | only in codegen
      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 "codegen/nv50_ir.h"
     24 #include "codegen/nv50_ir_target.h"
     25 
     26 #define __STDC_FORMAT_MACROS
     27 #include <inttypes.h>
     28 
     29 namespace nv50_ir {
     30 
     31 enum TextStyle
     32 {
     33    TXT_DEFAULT,
     34    TXT_GPR,
     35    TXT_REGISTER,
     36    TXT_FLAGS,
     37    TXT_MEM,
     38    TXT_IMMD,
     39    TXT_BRA,
     40    TXT_INSN
     41 };
     42 
     43 static const char *_colour[8] =
     44 {
     45    "\x1b[00m",
     46    "\x1b[34m",
     47    "\x1b[35m",
     48    "\x1b[35m",
     49    "\x1b[36m",
     50    "\x1b[33m",
     51    "\x1b[37m",
     52    "\x1b[32m"
     53 };
     54 
     55 static const char *_nocolour[8] =
     56 {
     57       "", "", "", "", "", "", "", ""
     58 };
     59 
     60 static const char **colour;
     61 
     62 static void init_colours()
     63 {
     64    if (getenv("NV50_PROG_DEBUG_NO_COLORS") != NULL)
     65       colour = _nocolour;
     66    else
     67       colour = _colour;
     68 }
     69 
     70 const char *operationStr[OP_LAST + 1] =
     71 {
     72    "nop",
     73    "phi",
     74    "union",
     75    "split",
     76    "merge",
     77    "consec",
     78    "mov",
     79    "ld",
     80    "st",
     81    "add",
     82    "sub",
     83    "mul",
     84    "div",
     85    "mod",
     86    "mad",
     87    "fma",
     88    "sad",
     89    "shladd",
     90    "abs",
     91    "neg",
     92    "not",
     93    "and",
     94    "or",
     95    "xor",
     96    "shl",
     97    "shr",
     98    "max",
     99    "min",
    100    "sat",
    101    "ceil",
    102    "floor",
    103    "trunc",
    104    "cvt",
    105    "set and",
    106    "set or",
    107    "set xor",
    108    "set",
    109    "selp",
    110    "slct",
    111    "rcp",
    112    "rsq",
    113    "lg2",
    114    "sin",
    115    "cos",
    116    "ex2",
    117    "exp",
    118    "log",
    119    "presin",
    120    "preex2",
    121    "sqrt",
    122    "pow",
    123    "bra",
    124    "call",
    125    "ret",
    126    "cont",
    127    "break",
    128    "preret",
    129    "precont",
    130    "prebreak",
    131    "brkpt",
    132    "joinat",
    133    "join",
    134    "discard",
    135    "exit",
    136    "membar",
    137    "vfetch",
    138    "pfetch",
    139    "afetch",
    140    "export",
    141    "linterp",
    142    "pinterp",
    143    "emit",
    144    "restart",
    145    "tex",
    146    "texbias",
    147    "texlod",
    148    "texfetch",
    149    "texquery",
    150    "texgrad",
    151    "texgather",
    152    "texquerylod",
    153    "texcsaa",
    154    "texprep",
    155    "suldb",
    156    "suldp",
    157    "sustb",
    158    "sustp",
    159    "suredb",
    160    "suredp",
    161    "sulea",
    162    "subfm",
    163    "suclamp",
    164    "sueau",
    165    "suq",
    166    "madsp",
    167    "texbar",
    168    "dfdx",
    169    "dfdy",
    170    "rdsv",
    171    "wrsv",
    172    "pixld",
    173    "quadop",
    174    "quadon",
    175    "quadpop",
    176    "popcnt",
    177    "insbf",
    178    "extbf",
    179    "bfind",
    180    "permt",
    181    "atom",
    182    "bar",
    183    "vadd",
    184    "vavg",
    185    "vmin",
    186    "vmax",
    187    "vsad",
    188    "vset",
    189    "vshr",
    190    "vshl",
    191    "vsel",
    192    "cctl",
    193    "shfl",
    194    "vote",
    195    "bufq",
    196    "(invalid)"
    197 };
    198 
    199 static const char *atomSubOpStr[] =
    200 {
    201    "add", "min", "max", "inc", "dec", "and", "or", "xor", "cas", "exch"
    202 };
    203 
    204 static const char *ldstSubOpStr[] =
    205 {
    206    "", "lock", "unlock"
    207 };
    208 
    209 static const char *subfmOpStr[] =
    210 {
    211    "", "3d"
    212 };
    213 
    214 static const char *shflOpStr[] =
    215 {
    216   "idx", "up", "down", "bfly"
    217 };
    218 
    219 static const char *pixldOpStr[] =
    220 {
    221    "count", "covmask", "offset", "cent_offset", "sampleid"
    222 };
    223 
    224 static const char *rcprsqOpStr[] =
    225 {
    226    "", "64h"
    227 };
    228 
    229 static const char *emitOpStr[] =
    230 {
    231    "", "restart"
    232 };
    233 
    234 static const char *cctlOpStr[] =
    235 {
    236    "", "", "", "", "", "iv", "ivall"
    237 };
    238 
    239 static const char *barOpStr[] =
    240 {
    241    "sync", "arrive", "red and", "red or", "red popc"
    242 };
    243 
    244 static const char *DataTypeStr[] =
    245 {
    246    "-",
    247    "u8", "s8",
    248    "u16", "s16",
    249    "u32", "s32",
    250    "u64", "s64",
    251    "f16", "f32", "f64",
    252    "b96", "b128"
    253 };
    254 
    255 static const char *RoundModeStr[] =
    256 {
    257    "", "rm", "rz", "rp", "rni", "rmi", "rzi", "rpi"
    258 };
    259 
    260 static const char *CondCodeStr[] =
    261 {
    262    "never",
    263    "lt",
    264    "eq",
    265    "le",
    266    "gt",
    267    "ne",
    268    "ge",
    269    "",
    270    "(invalid)",
    271    "ltu",
    272    "equ",
    273    "leu",
    274    "gtu",
    275    "neu",
    276    "geu",
    277    "",
    278    "no",
    279    "nc",
    280    "ns",
    281    "na",
    282    "a",
    283    "s",
    284    "c",
    285    "o"
    286 };
    287 
    288 static const char *SemanticStr[SV_LAST + 1] =
    289 {
    290    "POSITION",
    291    "VERTEX_ID",
    292    "INSTANCE_ID",
    293    "INVOCATION_ID",
    294    "PRIMITIVE_ID",
    295    "VERTEX_COUNT",
    296    "LAYER",
    297    "VIEWPORT_INDEX",
    298    "Y_DIR",
    299    "FACE",
    300    "POINT_SIZE",
    301    "POINT_COORD",
    302    "CLIP_DISTANCE",
    303    "SAMPLE_INDEX",
    304    "SAMPLE_POS",
    305    "SAMPLE_MASK",
    306    "TESS_OUTER",
    307    "TESS_INNER",
    308    "TESS_COORD",
    309    "TID",
    310    "CTAID",
    311    "NTID",
    312    "GRIDID",
    313    "NCTAID",
    314    "LANEID",
    315    "PHYSID",
    316    "NPHYSID",
    317    "CLOCK",
    318    "LBASE",
    319    "SBASE",
    320    "VERTEX_STRIDE",
    321    "INVOCATION_INFO",
    322    "THREAD_KILL",
    323    "BASEVERTEX",
    324    "BASEINSTANCE",
    325    "DRAWID",
    326    "WORK_DIM",
    327    "?",
    328    "(INVALID)"
    329 };
    330 
    331 static const char *interpStr[16] =
    332 {
    333    "pass",
    334    "mul",
    335    "flat",
    336    "sc",
    337    "cent pass",
    338    "cent mul",
    339    "cent flat",
    340    "cent sc",
    341    "off pass",
    342    "off mul",
    343    "off flat",
    344    "off sc",
    345    "samp pass",
    346    "samp mul",
    347    "samp flat",
    348    "samp sc"
    349 };
    350 
    351 #define PRINT(args...)                                \
    352    do {                                               \
    353       pos += snprintf(&buf[pos], size - pos, args);   \
    354    } while(0)
    355 
    356 #define SPACE_PRINT(cond, args...)                      \
    357    do {                                                 \
    358       if (cond)                                         \
    359          buf[pos++] = ' ';                              \
    360       pos += snprintf(&buf[pos], size - pos, args);     \
    361    } while(0)
    362 
    363 #define SPACE()                                    \
    364    do {                                            \
    365       if (pos < size)                              \
    366          buf[pos++] = ' ';                         \
    367    } while(0)
    368 
    369 int Modifier::print(char *buf, size_t size) const
    370 {
    371    size_t pos = 0;
    372 
    373    if (bits)
    374       PRINT("%s", colour[TXT_INSN]);
    375 
    376    size_t base = pos;
    377 
    378    if (bits & NV50_IR_MOD_NOT)
    379       PRINT("not");
    380    if (bits & NV50_IR_MOD_SAT)
    381       SPACE_PRINT(pos > base && pos < size, "sat");
    382    if (bits & NV50_IR_MOD_NEG)
    383       SPACE_PRINT(pos > base && pos < size, "neg");
    384    if (bits & NV50_IR_MOD_ABS)
    385       SPACE_PRINT(pos > base && pos < size, "abs");
    386 
    387    return pos;
    388 }
    389 
    390 int LValue::print(char *buf, size_t size, DataType ty) const
    391 {
    392    const char *postFix = "";
    393    size_t pos = 0;
    394    int idx = join->reg.data.id >= 0 ? join->reg.data.id : id;
    395    char p = join->reg.data.id >= 0 ? '$' : '%';
    396    char r;
    397    int col = TXT_DEFAULT;
    398 
    399    switch (reg.file) {
    400    case FILE_GPR:
    401       r = 'r'; col = TXT_GPR;
    402       if (reg.size == 2) {
    403          if (p == '$') {
    404             postFix = (idx & 1) ? "h" : "l";
    405             idx /= 2;
    406          } else {
    407             postFix = "s";
    408          }
    409       } else
    410       if (reg.size == 8) {
    411          postFix = "d";
    412       } else
    413       if (reg.size == 16) {
    414          postFix = "q";
    415       } else
    416       if (reg.size == 12) {
    417          postFix = "t";
    418       }
    419       break;
    420    case FILE_PREDICATE:
    421       r = 'p'; col = TXT_REGISTER;
    422       if (reg.size == 2)
    423          postFix = "d";
    424       else
    425       if (reg.size == 4)
    426          postFix = "q";
    427       break;
    428    case FILE_FLAGS:
    429       r = 'c'; col = TXT_FLAGS;
    430       break;
    431    case FILE_ADDRESS:
    432       r = 'a'; col = TXT_REGISTER;
    433       break;
    434    default:
    435       assert(!"invalid file for lvalue");
    436       r = '?';
    437       break;
    438    }
    439 
    440    PRINT("%s%c%c%i%s", colour[col], p, r, idx, postFix);
    441 
    442    return pos;
    443 }
    444 
    445 int ImmediateValue::print(char *buf, size_t size, DataType ty) const
    446 {
    447    size_t pos = 0;
    448 
    449    PRINT("%s", colour[TXT_IMMD]);
    450 
    451    switch (ty) {
    452    case TYPE_F32: PRINT("%f", reg.data.f32); break;
    453    case TYPE_F64: PRINT("%f", reg.data.f64); break;
    454    case TYPE_U8:  PRINT("0x%02x", reg.data.u8); break;
    455    case TYPE_S8:  PRINT("%i", reg.data.s8); break;
    456    case TYPE_U16: PRINT("0x%04x", reg.data.u16); break;
    457    case TYPE_S16: PRINT("%i", reg.data.s16); break;
    458    case TYPE_U32: PRINT("0x%08x", reg.data.u32); break;
    459    case TYPE_S32: PRINT("%i", reg.data.s32); break;
    460    case TYPE_U64:
    461    case TYPE_S64:
    462    default:
    463       PRINT("0x%016" PRIx64, reg.data.u64);
    464       break;
    465    }
    466    return pos;
    467 }
    468 
    469 int Symbol::print(char *buf, size_t size, DataType ty) const
    470 {
    471    return print(buf, size, NULL, NULL, ty);
    472 }
    473 
    474 int Symbol::print(char *buf, size_t size,
    475                   Value *rel, Value *dimRel, DataType ty) const
    476 {
    477    size_t pos = 0;
    478    char c;
    479 
    480    if (ty == TYPE_NONE)
    481       ty = typeOfSize(reg.size);
    482 
    483    if (reg.file == FILE_SYSTEM_VALUE) {
    484       PRINT("%ssv[%s%s:%i%s", colour[TXT_MEM],
    485             colour[TXT_REGISTER],
    486             SemanticStr[reg.data.sv.sv], reg.data.sv.index, colour[TXT_MEM]);
    487       if (rel) {
    488          PRINT("%s+", colour[TXT_DEFAULT]);
    489          pos += rel->print(&buf[pos], size - pos);
    490       }
    491       PRINT("%s]", colour[TXT_MEM]);
    492       return pos;
    493    }
    494 
    495    switch (reg.file) {
    496    case FILE_MEMORY_CONST:  c = 'c'; break;
    497    case FILE_SHADER_INPUT:  c = 'a'; break;
    498    case FILE_SHADER_OUTPUT: c = 'o'; break;
    499    case FILE_MEMORY_BUFFER: c = 'b'; break; // Only used before lowering
    500    case FILE_MEMORY_GLOBAL: c = 'g'; break;
    501    case FILE_MEMORY_SHARED: c = 's'; break;
    502    case FILE_MEMORY_LOCAL:  c = 'l'; break;
    503    default:
    504       assert(!"invalid file");
    505       c = '?';
    506       break;
    507    }
    508 
    509    if (c == 'c')
    510       PRINT("%s%c%i[", colour[TXT_MEM], c, reg.fileIndex);
    511    else
    512       PRINT("%s%c[", colour[TXT_MEM], c);
    513 
    514    if (dimRel) {
    515       pos += dimRel->print(&buf[pos], size - pos, TYPE_S32);
    516       PRINT("%s][", colour[TXT_MEM]);
    517    }
    518 
    519    if (rel) {
    520       pos += rel->print(&buf[pos], size - pos);
    521       PRINT("%s%c", colour[TXT_DEFAULT], (reg.data.offset < 0) ? '-' : '+');
    522    } else {
    523       assert(reg.data.offset >= 0);
    524    }
    525    PRINT("%s0x%x%s]", colour[TXT_IMMD], abs(reg.data.offset), colour[TXT_MEM]);
    526 
    527    return pos;
    528 }
    529 
    530 void Instruction::print() const
    531 {
    532    #define BUFSZ 512
    533 
    534    const size_t size = BUFSZ;
    535 
    536    char buf[BUFSZ];
    537    int s, d;
    538    size_t pos = 0;
    539 
    540    PRINT("%s", colour[TXT_INSN]);
    541 
    542    if (join)
    543       PRINT("join ");
    544 
    545    if (predSrc >= 0) {
    546       const size_t pre = pos;
    547       if (getSrc(predSrc)->reg.file == FILE_PREDICATE) {
    548          if (cc == CC_NOT_P)
    549             PRINT("not");
    550       } else {
    551          PRINT("%s", CondCodeStr[cc]);
    552       }
    553       if (pos > pre)
    554          SPACE();
    555       pos += getSrc(predSrc)->print(&buf[pos], BUFSZ - pos);
    556       PRINT(" %s", colour[TXT_INSN]);
    557    }
    558 
    559    if (saturate)
    560       PRINT("sat ");
    561 
    562    if (asFlow()) {
    563       PRINT("%s", operationStr[op]);
    564       if (asFlow()->indirect)
    565          PRINT(" ind");
    566       if (asFlow()->absolute)
    567          PRINT(" abs");
    568       if (op == OP_CALL && asFlow()->builtin) {
    569          PRINT(" %sBUILTIN:%i", colour[TXT_BRA], asFlow()->target.builtin);
    570       } else
    571       if (op == OP_CALL && asFlow()->target.fn) {
    572          PRINT(" %s%s:%i", colour[TXT_BRA],
    573                asFlow()->target.fn->getName(),
    574                asFlow()->target.fn->getLabel());
    575       } else
    576       if (asFlow()->target.bb)
    577          PRINT(" %sBB:%i", colour[TXT_BRA], asFlow()->target.bb->getId());
    578    } else {
    579       PRINT("%s ", operationStr[op]);
    580       if (op == OP_LINTERP || op == OP_PINTERP)
    581          PRINT("%s ", interpStr[ipa]);
    582       switch (op) {
    583       case OP_SUREDP:
    584       case OP_SUREDB:
    585       case OP_ATOM:
    586          if (subOp < ARRAY_SIZE(atomSubOpStr))
    587             PRINT("%s ", atomSubOpStr[subOp]);
    588          break;
    589       case OP_LOAD:
    590       case OP_STORE:
    591          if (subOp < ARRAY_SIZE(ldstSubOpStr))
    592             PRINT("%s ", ldstSubOpStr[subOp]);
    593          break;
    594       case OP_SUBFM:
    595          if (subOp < ARRAY_SIZE(subfmOpStr))
    596             PRINT("%s ", subfmOpStr[subOp]);
    597          break;
    598       case OP_SHFL:
    599          if (subOp < ARRAY_SIZE(shflOpStr))
    600             PRINT("%s ", shflOpStr[subOp]);
    601          break;
    602       case OP_PIXLD:
    603          if (subOp < ARRAY_SIZE(pixldOpStr))
    604             PRINT("%s ", pixldOpStr[subOp]);
    605          break;
    606       case OP_RCP:
    607       case OP_RSQ:
    608          if (subOp < ARRAY_SIZE(rcprsqOpStr))
    609             PRINT("%s ", rcprsqOpStr[subOp]);
    610          break;
    611       case OP_EMIT:
    612          if (subOp < ARRAY_SIZE(emitOpStr))
    613             PRINT("%s ", emitOpStr[subOp]);
    614          break;
    615       case OP_CCTL:
    616          if (subOp < ARRAY_SIZE(cctlOpStr))
    617             PRINT("%s ", cctlOpStr[subOp]);
    618          break;
    619       case OP_BAR:
    620          if (subOp < ARRAY_SIZE(barOpStr))
    621             PRINT("%s ", barOpStr[subOp]);
    622          break;
    623       default:
    624          if (subOp)
    625             PRINT("(SUBOP:%u) ", subOp);
    626          break;
    627       }
    628       if (perPatch)
    629          PRINT("patch ");
    630       if (asTex())
    631          PRINT("%s %s$r%u $s%u %s", asTex()->tex.target.getName(),
    632                colour[TXT_MEM], asTex()->tex.r, asTex()->tex.s,
    633                colour[TXT_INSN]);
    634       if (postFactor)
    635          PRINT("x2^%i ", postFactor);
    636       PRINT("%s%s", dnz ? "dnz " : (ftz ? "ftz " : ""),  DataTypeStr[dType]);
    637    }
    638 
    639    if (rnd != ROUND_N)
    640       PRINT(" %s", RoundModeStr[rnd]);
    641 
    642    if (defExists(1))
    643       PRINT(" {");
    644    for (d = 0; defExists(d); ++d) {
    645       SPACE();
    646       pos += getDef(d)->print(&buf[pos], size - pos);
    647    }
    648    if (d > 1)
    649       PRINT(" %s}", colour[TXT_INSN]);
    650    else
    651    if (!d && !asFlow())
    652       PRINT(" %s#", colour[TXT_INSN]);
    653 
    654    if (asCmp())
    655       PRINT(" %s%s", colour[TXT_INSN], CondCodeStr[asCmp()->setCond]);
    656 
    657    if (sType != dType)
    658       PRINT(" %s%s", colour[TXT_INSN], DataTypeStr[sType]);
    659 
    660    for (s = 0; srcExists(s); ++s) {
    661       if (s == predSrc || src(s).usedAsPtr)
    662          continue;
    663       const size_t pre = pos;
    664       SPACE();
    665       pos += src(s).mod.print(&buf[pos], BUFSZ - pos);
    666       if (pos > pre + 1)
    667          SPACE();
    668       if (src(s).isIndirect(0) || src(s).isIndirect(1))
    669          pos += getSrc(s)->asSym()->print(&buf[pos], BUFSZ - pos,
    670                                           getIndirect(s, 0),
    671                                           getIndirect(s, 1));
    672       else
    673          pos += getSrc(s)->print(&buf[pos], BUFSZ - pos, sType);
    674    }
    675    if (exit)
    676       PRINT("%s exit", colour[TXT_INSN]);
    677 
    678    PRINT("%s", colour[TXT_DEFAULT]);
    679 
    680    buf[MIN2(pos, BUFSZ - 1)] = 0;
    681 
    682    INFO("%s (%u)\n", buf, encSize);
    683 }
    684 
    685 class PrintPass : public Pass
    686 {
    687 public:
    688    PrintPass() : serial(0) { }
    689 
    690    virtual bool visit(Function *);
    691    virtual bool visit(BasicBlock *);
    692    virtual bool visit(Instruction *);
    693 
    694 private:
    695    int serial;
    696 };
    697 
    698 bool
    699 PrintPass::visit(Function *fn)
    700 {
    701    char str[16];
    702 
    703    INFO("\n%s:%i (", fn->getName(), fn->getLabel());
    704 
    705    if (!fn->outs.empty())
    706       INFO("out");
    707    for (std::deque<ValueRef>::iterator it = fn->outs.begin();
    708         it != fn->outs.end();
    709         ++it) {
    710       it->get()->print(str, sizeof(str), typeOfSize(it->get()->reg.size));
    711       INFO(" %s", str);
    712    }
    713 
    714    if (!fn->ins.empty())
    715       INFO("%s%sin", colour[TXT_DEFAULT], fn->outs.empty() ? "" : ", ");
    716    for (std::deque<ValueDef>::iterator it = fn->ins.begin();
    717         it != fn->ins.end();
    718         ++it) {
    719       it->get()->print(str, sizeof(str), typeOfSize(it->get()->reg.size));
    720       INFO(" %s", str);
    721    }
    722    INFO("%s)\n", colour[TXT_DEFAULT]);
    723 
    724    return true;
    725 }
    726 
    727 bool
    728 PrintPass::visit(BasicBlock *bb)
    729 {
    730 #if 0
    731    INFO("---\n");
    732    for (Graph::EdgeIterator ei = bb->cfg.incident(); !ei.end(); ei.next())
    733       INFO(" <- BB:%i (%s)\n",
    734            BasicBlock::get(ei.getNode())->getId(),
    735            ei.getEdge()->typeStr());
    736 #endif
    737    INFO("BB:%i (%u instructions) - ", bb->getId(), bb->getInsnCount());
    738 
    739    if (bb->idom())
    740       INFO("idom = BB:%i, ", bb->idom()->getId());
    741 
    742    INFO("df = { ");
    743    for (DLList::Iterator df = bb->getDF().iterator(); !df.end(); df.next())
    744       INFO("BB:%i ", BasicBlock::get(df)->getId());
    745 
    746    INFO("}\n");
    747 
    748    for (Graph::EdgeIterator ei = bb->cfg.outgoing(); !ei.end(); ei.next())
    749       INFO(" -> BB:%i (%s)\n",
    750            BasicBlock::get(ei.getNode())->getId(),
    751            ei.getEdge()->typeStr());
    752 
    753    return true;
    754 }
    755 
    756 bool
    757 PrintPass::visit(Instruction *insn)
    758 {
    759    INFO("%3i: ", serial++);
    760    insn->print();
    761    return true;
    762 }
    763 
    764 void
    765 Function::print()
    766 {
    767    PrintPass pass;
    768    pass.run(this, true, false);
    769 }
    770 
    771 void
    772 Program::print()
    773 {
    774    PrintPass pass;
    775    init_colours();
    776    pass.run(this, true, false);
    777 }
    778 
    779 void
    780 Function::printLiveIntervals() const
    781 {
    782    INFO("printing live intervals ...\n");
    783 
    784    for (ArrayList::Iterator it = allLValues.iterator(); !it.end(); it.next()) {
    785       const Value *lval = Value::get(it)->asLValue();
    786       if (lval && !lval->livei.isEmpty()) {
    787          INFO("livei(%%%i): ", lval->id);
    788          lval->livei.print();
    789       }
    790    }
    791 }
    792 
    793 } // namespace nv50_ir
    794