ab39f9fdf6302a46d042f986855a42ef7bf07c63
2 * Copyright 2011 Christoph Bumiller
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
23 #include "codegen/nv50_ir.h"
24 #include "codegen/nv50_ir_target.h"
42 static const char *_colour
[8] =
54 static const char *_nocolour
[8] =
56 "", "", "", "", "", "", "", ""
59 static const char **colour
;
61 static void init_colours()
63 if (getenv("NV50_PROG_DEBUG_NO_COLORS") != NULL
)
69 const char *operationStr
[OP_LAST
+ 1] =
198 static const char *atomSubOpStr
[] =
200 "add", "min", "max", "inc", "dec", "and", "or", "xor", "cas", "exch"
203 static const char *ldstSubOpStr
[] =
208 static const char *subfmOpStr
[] =
213 static const char *shflOpStr
[] =
215 "idx", "up", "down", "bfly"
218 static const char *pixldOpStr
[] =
220 "count", "covmask", "offset", "cent_offset", "sampleid"
223 static const char *rcprsqOpStr
[] =
228 static const char *emitOpStr
[] =
233 static const char *cctlOpStr
[] =
235 "", "", "", "", "", "iv", "ivall"
238 static const char *barOpStr
[] =
240 "sync", "arrive", "red and", "red or", "red popc"
243 static const char *DataTypeStr
[] =
254 static const char *RoundModeStr
[] =
256 "", "rm", "rz", "rp", "rni", "rmi", "rzi", "rpi"
259 static const char *CondCodeStr
[] =
287 static const char *SemanticStr
[SV_LAST
+ 1] =
335 static const char *interpStr
[16] =
355 #define PRINT(args...) \
357 pos += snprintf(&buf[pos], size - pos, args); \
360 #define SPACE_PRINT(cond, args...) \
364 pos += snprintf(&buf[pos], size - pos, args); \
373 int Modifier::print(char *buf
, size_t size
) const
378 PRINT("%s", colour
[TXT_INSN
]);
382 if (bits
& NV50_IR_MOD_NOT
)
384 if (bits
& NV50_IR_MOD_SAT
)
385 SPACE_PRINT(pos
> base
&& pos
< size
, "sat");
386 if (bits
& NV50_IR_MOD_NEG
)
387 SPACE_PRINT(pos
> base
&& pos
< size
, "neg");
388 if (bits
& NV50_IR_MOD_ABS
)
389 SPACE_PRINT(pos
> base
&& pos
< size
, "abs");
394 int LValue::print(char *buf
, size_t size
, DataType ty
) const
396 const char *postFix
= "";
398 int idx
= join
->reg
.data
.id
>= 0 ? join
->reg
.data
.id
: id
;
399 char p
= join
->reg
.data
.id
>= 0 ? '$' : '%';
401 int col
= TXT_DEFAULT
;
405 r
= 'r'; col
= TXT_GPR
;
408 postFix
= (idx
& 1) ? "h" : "l";
417 if (reg
.size
== 16) {
420 if (reg
.size
== 12) {
425 r
= 'p'; col
= TXT_REGISTER
;
433 r
= 'c'; col
= TXT_FLAGS
;
436 r
= 'a'; col
= TXT_REGISTER
;
439 assert(!"invalid file for lvalue");
444 PRINT("%s%c%c%i%s", colour
[col
], p
, r
, idx
, postFix
);
449 int ImmediateValue::print(char *buf
, size_t size
, DataType ty
) const
453 PRINT("%s", colour
[TXT_IMMD
]);
456 case TYPE_F32
: PRINT("%f", reg
.data
.f32
); break;
457 case TYPE_F64
: PRINT("%f", reg
.data
.f64
); break;
458 case TYPE_U8
: PRINT("0x%02x", reg
.data
.u8
); break;
459 case TYPE_S8
: PRINT("%i", reg
.data
.s8
); break;
460 case TYPE_U16
: PRINT("0x%04x", reg
.data
.u16
); break;
461 case TYPE_S16
: PRINT("%i", reg
.data
.s16
); break;
462 case TYPE_U32
: PRINT("0x%08x", reg
.data
.u32
); break;
463 case TYPE_S32
: PRINT("%i", reg
.data
.s32
); break;
467 PRINT("0x%016" PRIx64
, reg
.data
.u64
);
473 int Symbol::print(char *buf
, size_t size
, DataType ty
) const
475 return print(buf
, size
, NULL
, NULL
, ty
);
478 int Symbol::print(char *buf
, size_t size
,
479 Value
*rel
, Value
*dimRel
, DataType ty
) const
485 ty
= typeOfSize(reg
.size
);
487 if (reg
.file
== FILE_SYSTEM_VALUE
) {
488 PRINT("%ssv[%s%s:%i%s", colour
[TXT_MEM
],
489 colour
[TXT_REGISTER
],
490 SemanticStr
[reg
.data
.sv
.sv
], reg
.data
.sv
.index
, colour
[TXT_MEM
]);
492 PRINT("%s+", colour
[TXT_DEFAULT
]);
493 pos
+= rel
->print(&buf
[pos
], size
- pos
);
495 PRINT("%s]", colour
[TXT_MEM
]);
500 case FILE_MEMORY_CONST
: c
= 'c'; break;
501 case FILE_SHADER_INPUT
: c
= 'a'; break;
502 case FILE_SHADER_OUTPUT
: c
= 'o'; break;
503 case FILE_MEMORY_BUFFER
: c
= 'b'; break; // Only used before lowering
504 case FILE_MEMORY_GLOBAL
: c
= 'g'; break;
505 case FILE_MEMORY_SHARED
: c
= 's'; break;
506 case FILE_MEMORY_LOCAL
: c
= 'l'; break;
508 assert(!"invalid file");
514 PRINT("%s%c%i[", colour
[TXT_MEM
], c
, reg
.fileIndex
);
516 PRINT("%s%c[", colour
[TXT_MEM
], c
);
519 pos
+= dimRel
->print(&buf
[pos
], size
- pos
, TYPE_S32
);
520 PRINT("%s][", colour
[TXT_MEM
]);
524 pos
+= rel
->print(&buf
[pos
], size
- pos
);
525 PRINT("%s%c", colour
[TXT_DEFAULT
], (reg
.data
.offset
< 0) ? '-' : '+');
527 assert(reg
.data
.offset
>= 0);
529 PRINT("%s0x%x%s]", colour
[TXT_IMMD
], abs(reg
.data
.offset
), colour
[TXT_MEM
]);
534 void Instruction::print() const
538 const size_t size
= BUFSZ
;
544 PRINT("%s", colour
[TXT_INSN
]);
550 const size_t pre
= pos
;
551 if (getSrc(predSrc
)->reg
.file
== FILE_PREDICATE
) {
555 PRINT("%s", CondCodeStr
[cc
]);
559 pos
+= getSrc(predSrc
)->print(&buf
[pos
], BUFSZ
- pos
);
560 PRINT(" %s", colour
[TXT_INSN
]);
567 PRINT("%s", operationStr
[op
]);
568 if (asFlow()->indirect
)
570 if (asFlow()->absolute
)
572 if (op
== OP_CALL
&& asFlow()->builtin
) {
573 PRINT(" %sBUILTIN:%i", colour
[TXT_BRA
], asFlow()->target
.builtin
);
575 if (op
== OP_CALL
&& asFlow()->target
.fn
) {
576 PRINT(" %s%s:%i", colour
[TXT_BRA
],
577 asFlow()->target
.fn
->getName(),
578 asFlow()->target
.fn
->getLabel());
580 if (asFlow()->target
.bb
)
581 PRINT(" %sBB:%i", colour
[TXT_BRA
], asFlow()->target
.bb
->getId());
583 PRINT("%s ", operationStr
[op
]);
584 if (op
== OP_LINTERP
|| op
== OP_PINTERP
)
585 PRINT("%s ", interpStr
[ipa
]);
590 if (subOp
< ARRAY_SIZE(atomSubOpStr
))
591 PRINT("%s ", atomSubOpStr
[subOp
]);
595 if (subOp
< ARRAY_SIZE(ldstSubOpStr
))
596 PRINT("%s ", ldstSubOpStr
[subOp
]);
599 if (subOp
< ARRAY_SIZE(subfmOpStr
))
600 PRINT("%s ", subfmOpStr
[subOp
]);
603 if (subOp
< ARRAY_SIZE(shflOpStr
))
604 PRINT("%s ", shflOpStr
[subOp
]);
607 if (subOp
< ARRAY_SIZE(pixldOpStr
))
608 PRINT("%s ", pixldOpStr
[subOp
]);
612 if (subOp
< ARRAY_SIZE(rcprsqOpStr
))
613 PRINT("%s ", rcprsqOpStr
[subOp
]);
616 if (subOp
< ARRAY_SIZE(emitOpStr
))
617 PRINT("%s ", emitOpStr
[subOp
]);
620 if (subOp
< ARRAY_SIZE(cctlOpStr
))
621 PRINT("%s ", cctlOpStr
[subOp
]);
624 if (subOp
< ARRAY_SIZE(barOpStr
))
625 PRINT("%s ", barOpStr
[subOp
]);
629 PRINT("(SUBOP:%u) ", subOp
);
635 PRINT("%s %s$r%u $s%u %s", asTex()->tex
.target
.getName(),
636 colour
[TXT_MEM
], asTex()->tex
.r
, asTex()->tex
.s
,
639 PRINT("x2^%i ", postFactor
);
640 PRINT("%s%s", dnz
? "dnz " : (ftz
? "ftz " : ""), DataTypeStr
[dType
]);
644 PRINT(" %s", RoundModeStr
[rnd
]);
648 for (d
= 0; defExists(d
); ++d
) {
650 pos
+= getDef(d
)->print(&buf
[pos
], size
- pos
);
653 PRINT(" %s}", colour
[TXT_INSN
]);
656 PRINT(" %s#", colour
[TXT_INSN
]);
659 PRINT(" %s%s", colour
[TXT_INSN
], CondCodeStr
[asCmp()->setCond
]);
662 PRINT(" %s%s", colour
[TXT_INSN
], DataTypeStr
[sType
]);
664 for (s
= 0; srcExists(s
); ++s
) {
665 if (s
== predSrc
|| src(s
).usedAsPtr
)
667 const size_t pre
= pos
;
669 pos
+= src(s
).mod
.print(&buf
[pos
], BUFSZ
- pos
);
672 if (src(s
).isIndirect(0) || src(s
).isIndirect(1))
673 pos
+= getSrc(s
)->asSym()->print(&buf
[pos
], BUFSZ
- pos
,
677 pos
+= getSrc(s
)->print(&buf
[pos
], BUFSZ
- pos
, sType
);
680 PRINT("%s exit", colour
[TXT_INSN
]);
682 PRINT("%s", colour
[TXT_DEFAULT
]);
684 buf
[MIN2(pos
, BUFSZ
- 1)] = 0;
686 INFO("%s (%u)\n", buf
, encSize
);
689 class PrintPass
: public Pass
692 PrintPass(bool omitLineNum
) : serial(0), omit_serial(omitLineNum
) { }
694 virtual bool visit(Function
*);
695 virtual bool visit(BasicBlock
*);
696 virtual bool visit(Instruction
*);
704 PrintPass::visit(Function
*fn
)
708 INFO("\n%s:%i (", fn
->getName(), fn
->getLabel());
710 if (!fn
->outs
.empty())
712 for (std::deque
<ValueRef
>::iterator it
= fn
->outs
.begin();
713 it
!= fn
->outs
.end();
715 it
->get()->print(str
, sizeof(str
), typeOfSize(it
->get()->reg
.size
));
719 if (!fn
->ins
.empty())
720 INFO("%s%sin", colour
[TXT_DEFAULT
], fn
->outs
.empty() ? "" : ", ");
721 for (std::deque
<ValueDef
>::iterator it
= fn
->ins
.begin();
724 it
->get()->print(str
, sizeof(str
), typeOfSize(it
->get()->reg
.size
));
727 INFO("%s)\n", colour
[TXT_DEFAULT
]);
733 PrintPass::visit(BasicBlock
*bb
)
737 for (Graph::EdgeIterator ei
= bb
->cfg
.incident(); !ei
.end(); ei
.next())
738 INFO(" <- BB:%i (%s)\n",
739 BasicBlock::get(ei
.getNode())->getId(),
740 ei
.getEdge()->typeStr());
742 INFO("BB:%i (%u instructions) - ", bb
->getId(), bb
->getInsnCount());
745 INFO("idom = BB:%i, ", bb
->idom()->getId());
748 for (DLList::Iterator df
= bb
->getDF().iterator(); !df
.end(); df
.next())
749 INFO("BB:%i ", BasicBlock::get(df
)->getId());
753 for (Graph::EdgeIterator ei
= bb
->cfg
.outgoing(); !ei
.end(); ei
.next())
754 INFO(" -> BB:%i (%s)\n",
755 BasicBlock::get(ei
.getNode())->getId(),
756 ei
.getEdge()->typeStr());
762 PrintPass::visit(Instruction
*insn
)
767 INFO("%3i: ", serial
);
776 PrintPass
pass(prog
->driver
->omitLineNum
);
777 pass
.run(this, true, false);
783 PrintPass
pass(driver
->omitLineNum
);
785 pass
.run(this, true, false);
789 Function::printLiveIntervals() const
791 INFO("printing live intervals ...\n");
793 for (ArrayList::Iterator it
= allLValues
.iterator(); !it
.end(); it
.next()) {
794 const Value
*lval
= Value::get(it
)->asLValue();
795 if (lval
&& !lval
->livei
.isEmpty()) {
796 INFO("livei(%%%i): ", lval
->id
);
802 } // namespace nv50_ir