Skip to content

Commit c505654

Browse files
[NVVM] Pretty Printing Immediate Arguments in LLVM Intrinsics
This patch adds LLVM infrastructure to support pretty printing of immediate arguments of the intrinsics. The motivation is to increase the readability of LLVM intrinsics and facilitate easy modifications and debugging of LLVM IR. This adds a property PrettyPrintImmArg<ArgIndex, "functionName"> to the intrinsic ImmArgs that enables printing self-explanatory inline comment for the immediate arguments. The addition of pretty print support can provide a simple, low-overhead feature that enhances usability of LLVM intrinsics without disrupting existing workflows. Signed-off-by: Dharuni R Acharya <[email protected]>
1 parent 40ea56f commit c505654

File tree

13 files changed

+286
-16
lines changed

13 files changed

+286
-16
lines changed

llvm/include/llvm/IR/Function.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -930,7 +930,8 @@ class LLVM_ABI Function : public GlobalObject, public ilist_node<Function> {
930930
/// AssemblyAnnotationWriter.
931931
void print(raw_ostream &OS, AssemblyAnnotationWriter *AAW = nullptr,
932932
bool ShouldPreserveUseListOrder = false,
933-
bool IsForDebug = false) const;
933+
bool IsForDebug = false,
934+
bool PrettyPrintIntrinsicArgs = false) const;
934935

935936
/// viewCFG - This function is meant for use from the debugger. You can just
936937
/// say 'call F->viewCFG()' and a ghostview window should pop up from the

llvm/include/llvm/IR/Intrinsics.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ class LLVMContext;
3030
class Module;
3131
class AttributeList;
3232
class AttributeSet;
33+
class raw_ostream;
34+
class Constant;
3335

3436
/// This namespace contains an enum with a value for every intrinsic/builtin
3537
/// function known by LLVM. The enum values are returned by
@@ -81,6 +83,9 @@ namespace Intrinsic {
8183
/// Returns true if the intrinsic can be overloaded.
8284
LLVM_ABI bool isOverloaded(ID id);
8385

86+
/// Returns true if the intrinsic has pretty printed immediate arguments.
87+
LLVM_ABI bool hasPrettyPrintedArgs(ID id);
88+
8489
/// isTargetIntrinsic - Returns true if IID is an intrinsic specific to a
8590
/// certain target. If it is a generic intrinsic false is returned.
8691
LLVM_ABI bool isTargetIntrinsic(ID IID);
@@ -284,6 +289,8 @@ namespace Intrinsic {
284289
/// N.
285290
LLVM_ABI Intrinsic::ID getDeinterleaveIntrinsicID(unsigned Factor);
286291

292+
LLVM_ABI void printImmArg(ID IID, unsigned ArgIdx, raw_ostream &OS, const Constant *ImmArgVal);
293+
287294
} // namespace Intrinsic
288295

289296
} // namespace llvm

llvm/include/llvm/IR/Intrinsics.td

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,13 @@ class NoUndef<AttrIndex idx> : IntrinsicProperty {
8787
int ArgNo = idx.Value;
8888
}
8989

90+
// PrettyPrintImmArg - The specified immediate argument has a custom pretty-print
91+
// function for diagnostic output.
92+
class PrettyPrintImmArg<AttrIndex idx, string funcname> : IntrinsicProperty {
93+
int ArgNo = idx.Value;
94+
string FunctionName = funcname;
95+
}
96+
9097
// NonNull - The return value or specified argument is not null.
9198
class NonNull<AttrIndex idx> : IntrinsicProperty {
9299
int ArgNo = idx.Value;

llvm/include/llvm/IR/IntrinsicsNVVM.td

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2871,7 +2871,14 @@ foreach sp = [0, 1] in {
28712871
defvar nargs = !size(args);
28722872
defvar scale_d_imm = ArgIndex<!sub(nargs, 1)>;
28732873
defvar scale_d_imm_range = [ImmArg<scale_d_imm>, Range<scale_d_imm, 0, 16>];
2874-
defvar intrinsic_properties = !listconcat(
2874+
2875+
// Check if this is the specific llvm.nvvm.tcgen05.mma.tensor intrinsic
2876+
defvar is_target_intrinsic = !and(!eq(sp, 0),
2877+
!eq(space, "tensor"),
2878+
!eq(scale_d, 0),
2879+
!eq(ashift, 0));
2880+
2881+
defvar base_properties = !listconcat(
28752882
mma.common_intr_props,
28762883
!if(!eq(scale_d, 1), scale_d_imm_range, []),
28772884
[Range<ArgIndex<nargs>, 0, !if(!eq(scale_d, 1), 2, 4)>, // kind
@@ -2881,6 +2888,13 @@ foreach sp = [0, 1] in {
28812888
]
28822889
);
28832890

2891+
defvar intrinsic_properties = !if(is_target_intrinsic,
2892+
!listconcat(base_properties,
2893+
[PrettyPrintImmArg<ArgIndex<nargs>, "printTcgen05MMAKind">,
2894+
PrettyPrintImmArg<ArgIndex<!add(nargs, 1)>, "printCTAGroupKind">,
2895+
PrettyPrintImmArg<ArgIndex<!add(nargs, 2)>, "printTcgen05CollectorUsageOp">]),
2896+
base_properties);
2897+
28842898
def mma.record:
28852899
DefaultAttrsIntrinsicFlags<[], args, flags, intrinsic_properties,
28862900
mma.intr>;

llvm/include/llvm/IR/Module.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -866,7 +866,8 @@ class LLVM_ABI Module {
866866
/// the assembly.
867867
void print(raw_ostream &OS, AssemblyAnnotationWriter *AAW,
868868
bool ShouldPreserveUseListOrder = false,
869-
bool IsForDebug = false) const;
869+
bool IsForDebug = false,
870+
bool PrettyPrintIntrinsicArgs = false) const;
870871

871872
/// Dump the module to stderr (for debugging).
872873
void dump() const;

llvm/include/llvm/IR/NVVMIntrinsicUtils.h

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
#include <stdint.h>
1919

2020
#include "llvm/ADT/APFloat.h"
21+
#include "llvm/ADT/APInt.h"
22+
#include "llvm/IR/Constants.h"
23+
#include "llvm/Support/raw_ostream.h"
2124
#include "llvm/IR/Intrinsics.h"
2225
#include "llvm/IR/IntrinsicsNVPTX.h"
2326

@@ -659,6 +662,66 @@ inline APFloat::roundingMode GetFMARoundingMode(Intrinsic::ID IntrinsicID) {
659662
llvm_unreachable("Invalid FP instrinsic rounding mode for NVVM fma");
660663
}
661664

665+
inline void printTcgen05MMAKind(raw_ostream &OS, const Constant *ImmArgVal) {
666+
if (const ConstantInt *CI = dyn_cast<ConstantInt>(ImmArgVal)) {
667+
uint64_t Val = CI->getZExtValue();
668+
switch (static_cast<Tcgen05MMAKind>(Val)) {
669+
case Tcgen05MMAKind::F16:
670+
OS << "kind::f16";
671+
return;
672+
case Tcgen05MMAKind::TF32:
673+
OS << "kind::tf32";
674+
return;
675+
case Tcgen05MMAKind::F8F6F4:
676+
OS << "kind::f8f6f4";
677+
return;
678+
case Tcgen05MMAKind::I8:
679+
OS << "kind::i8";
680+
return;
681+
}
682+
}
683+
llvm_unreachable("printTcgen05MMAKind called with invalid value for immediate argument");
684+
}
685+
686+
inline void printTcgen05CollectorUsageOp(raw_ostream &OS, const Constant *ImmArgVal) {
687+
if (const ConstantInt *CI = dyn_cast<ConstantInt>(ImmArgVal)) {
688+
uint64_t Val = CI->getZExtValue();
689+
switch (static_cast<Tcgen05CollectorUsageOp>(Val)) {
690+
case Tcgen05CollectorUsageOp::DISCARD:
691+
OS << "collector::a::discard";
692+
return;
693+
case Tcgen05CollectorUsageOp::LASTUSE:
694+
OS << "collector::a::lastuse";
695+
return;
696+
case Tcgen05CollectorUsageOp::FILL:
697+
OS << "collector::a::fill";
698+
return;
699+
case Tcgen05CollectorUsageOp::USE:
700+
OS << "collector::a::use";
701+
return;
702+
}
703+
}
704+
llvm_unreachable("printTcgen05CollectorUsageOp called with invalid value for immediate argument");
705+
}
706+
707+
inline void printCTAGroupKind(raw_ostream &OS, const Constant *ImmArgVal) {
708+
if (const ConstantInt *CI = dyn_cast<ConstantInt>(ImmArgVal)) {
709+
uint64_t Val = CI->getZExtValue();
710+
switch (static_cast<CTAGroupKind>(Val)) {
711+
case CTAGroupKind::CG_NONE:
712+
OS << "cta_group::0";
713+
return;
714+
case CTAGroupKind::CG_1:
715+
OS << "cta_group::1";
716+
return;
717+
case CTAGroupKind::CG_2:
718+
OS << "cta_group::2";
719+
return;
720+
}
721+
}
722+
llvm_unreachable("printCTAGroupKind called with invalid value for immediate argument");
723+
}
724+
662725
} // namespace nvvm
663726
} // namespace llvm
664727
#endif // LLVM_IR_NVVMINTRINSICUTILS_H

llvm/lib/IR/AsmWriter.cpp

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
#include "llvm/IR/Instruction.h"
5454
#include "llvm/IR/Instructions.h"
5555
#include "llvm/IR/IntrinsicInst.h"
56+
#include "llvm/IR/Intrinsics.h"
5657
#include "llvm/IR/LLVMContext.h"
5758
#include "llvm/IR/Metadata.h"
5859
#include "llvm/IR/Module.h"
@@ -2831,6 +2832,7 @@ class AssemblyWriter {
28312832
SetVector<const Comdat *> Comdats;
28322833
bool IsForDebug;
28332834
bool ShouldPreserveUseListOrder;
2835+
bool PrettyPrintIntrinsicArgs;
28342836
UseListOrderMap UseListOrders;
28352837
SmallVector<StringRef, 8> MDNames;
28362838
/// Synchronization scope names registered with LLVMContext.
@@ -2841,7 +2843,8 @@ class AssemblyWriter {
28412843
/// Construct an AssemblyWriter with an external SlotTracker
28422844
AssemblyWriter(formatted_raw_ostream &o, SlotTracker &Mac, const Module *M,
28432845
AssemblyAnnotationWriter *AAW, bool IsForDebug,
2844-
bool ShouldPreserveUseListOrder = false);
2846+
bool ShouldPreserveUseListOrder = false,
2847+
bool PrettyPrintIntrinsicArgs = false);
28452848

28462849
AssemblyWriter(formatted_raw_ostream &o, SlotTracker &Mac,
28472850
const ModuleSummaryIndex *Index, bool IsForDebug);
@@ -2930,10 +2933,12 @@ class AssemblyWriter {
29302933

29312934
AssemblyWriter::AssemblyWriter(formatted_raw_ostream &o, SlotTracker &Mac,
29322935
const Module *M, AssemblyAnnotationWriter *AAW,
2933-
bool IsForDebug, bool ShouldPreserveUseListOrder)
2936+
bool IsForDebug, bool ShouldPreserveUseListOrder,
2937+
bool PrettyPrintIntrinsicArgs)
29342938
: Out(o), TheModule(M), Machine(Mac), TypePrinter(M), AnnotationWriter(AAW),
29352939
IsForDebug(IsForDebug),
2936-
ShouldPreserveUseListOrder(ShouldPreserveUseListOrder) {
2940+
ShouldPreserveUseListOrder(ShouldPreserveUseListOrder),
2941+
PrettyPrintIntrinsicArgs(PrettyPrintIntrinsicArgs) {
29372942
if (!TheModule)
29382943
return;
29392944
for (const GlobalObject &GO : TheModule->global_objects())
@@ -2944,7 +2949,8 @@ AssemblyWriter::AssemblyWriter(formatted_raw_ostream &o, SlotTracker &Mac,
29442949
AssemblyWriter::AssemblyWriter(formatted_raw_ostream &o, SlotTracker &Mac,
29452950
const ModuleSummaryIndex *Index, bool IsForDebug)
29462951
: Out(o), TheIndex(Index), Machine(Mac), TypePrinter(/*Module=*/nullptr),
2947-
IsForDebug(IsForDebug), ShouldPreserveUseListOrder(false) {}
2952+
IsForDebug(IsForDebug), ShouldPreserveUseListOrder(false),
2953+
PrettyPrintIntrinsicArgs(false) {}
29482954

29492955
void AssemblyWriter::writeOperand(const Value *Operand, bool PrintType) {
29502956
if (!Operand) {
@@ -4561,12 +4567,38 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
45614567
Out << ' ';
45624568
writeOperand(Operand, false);
45634569
Out << '(';
4570+
bool HasPrettyPrintedArgs = PrettyPrintIntrinsicArgs && isa<IntrinsicInst>(CI) &&
4571+
Intrinsic::hasPrettyPrintedArgs(CI->getIntrinsicID());
4572+
45644573
ListSeparator LS;
4565-
for (unsigned op = 0, Eop = CI->arg_size(); op < Eop; ++op) {
4566-
Out << LS;
4567-
writeParamOperand(CI->getArgOperand(op), PAL.getParamAttrs(op));
4568-
}
4574+
if (HasPrettyPrintedArgs) {
4575+
Function *CalledFunc = CI->getCalledFunction();
4576+
auto PrintArgComment = [&](unsigned ArgNo) {
4577+
if (!CalledFunc->hasParamAttribute(ArgNo, Attribute::ImmArg))
4578+
return;
4579+
const Constant *ConstArg = dyn_cast<Constant>(CI->getArgOperand(ArgNo));
4580+
if (!ConstArg)
4581+
return;
4582+
std::string ArgComment;
4583+
raw_string_ostream ArgCommentStream(ArgComment);
4584+
Intrinsic::ID IID = CalledFunc->getIntrinsicID();
4585+
Intrinsic::printImmArg(IID, ArgNo, ArgCommentStream, ConstArg);
4586+
if (ArgComment.empty())
4587+
return;
4588+
Out << "/* " << ArgComment << " */ ";
4589+
};
45694590

4591+
for (unsigned ArgNo = 0, NumArgs = CI->arg_size(); ArgNo < NumArgs; ++ArgNo) {
4592+
Out << LS;
4593+
PrintArgComment(ArgNo);
4594+
writeParamOperand(CI->getArgOperand(ArgNo), PAL.getParamAttrs(ArgNo));
4595+
}
4596+
} else {
4597+
for (unsigned op = 0, Eop = CI->arg_size(); op < Eop; ++op) {
4598+
Out << LS;
4599+
writeParamOperand(CI->getArgOperand(op), PAL.getParamAttrs(op));
4600+
}
4601+
}
45704602
// Emit an ellipsis if this is a musttail call in a vararg function. This
45714603
// is only to aid readability, musttail calls forward varargs by default.
45724604
if (CI->isMustTailCall() && CI->getParent() &&
@@ -4991,12 +5023,14 @@ void AssemblyWriter::printUseLists(const Function *F) {
49915023

49925024
void Function::print(raw_ostream &ROS, AssemblyAnnotationWriter *AAW,
49935025
bool ShouldPreserveUseListOrder,
4994-
bool IsForDebug) const {
5026+
bool IsForDebug,
5027+
bool PrettyPrintIntrinsicArgs) const {
49955028
SlotTracker SlotTable(this->getParent());
49965029
formatted_raw_ostream OS(ROS);
49975030
AssemblyWriter W(OS, SlotTable, this->getParent(), AAW,
49985031
IsForDebug,
4999-
ShouldPreserveUseListOrder);
5032+
ShouldPreserveUseListOrder,
5033+
PrettyPrintIntrinsicArgs);
50005034
W.printFunction(this);
50015035
}
50025036

@@ -5012,11 +5046,11 @@ void BasicBlock::print(raw_ostream &ROS, AssemblyAnnotationWriter *AAW,
50125046
}
50135047

50145048
void Module::print(raw_ostream &ROS, AssemblyAnnotationWriter *AAW,
5015-
bool ShouldPreserveUseListOrder, bool IsForDebug) const {
5049+
bool ShouldPreserveUseListOrder, bool IsForDebug, bool PrettyPrintIntrinsicArgs) const {
50165050
SlotTracker SlotTable(this);
50175051
formatted_raw_ostream OS(ROS);
50185052
AssemblyWriter W(OS, SlotTable, this, AAW, IsForDebug,
5019-
ShouldPreserveUseListOrder);
5053+
ShouldPreserveUseListOrder, PrettyPrintIntrinsicArgs);
50205054
W.printModule(this);
50215055
}
50225056

llvm/lib/IR/Intrinsics.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "llvm/IR/IntrinsicsLoongArch.h"
2424
#include "llvm/IR/IntrinsicsMips.h"
2525
#include "llvm/IR/IntrinsicsNVPTX.h"
26+
#include "llvm/IR/NVVMIntrinsicUtils.h"
2627
#include "llvm/IR/IntrinsicsPowerPC.h"
2728
#include "llvm/IR/IntrinsicsR600.h"
2829
#include "llvm/IR/IntrinsicsRISCV.h"
@@ -601,6 +602,12 @@ bool Intrinsic::isOverloaded(ID id) {
601602
#undef GET_INTRINSIC_OVERLOAD_TABLE
602603
}
603604

605+
bool Intrinsic::hasPrettyPrintedArgs(ID id) {
606+
#define GET_INTRINSIC_PRETTY_PRINT_TABLE
607+
#include "llvm/IR/IntrinsicImpl.inc"
608+
#undef GET_INTRINSIC_PRETTY_PRINT_TABLE
609+
}
610+
604611
/// Table of per-target intrinsic name tables.
605612
#define GET_INTRINSIC_TARGET_DATA
606613
#include "llvm/IR/IntrinsicImpl.inc"
@@ -1129,3 +1136,7 @@ Intrinsic::ID Intrinsic::getDeinterleaveIntrinsicID(unsigned Factor) {
11291136
assert(Factor >= 2 && Factor <= 8 && "Unexpected factor");
11301137
return InterleaveIntrinsics[Factor - 2].Deinterleave;
11311138
}
1139+
1140+
#define GET_INTRINSIC_PRETTY_PRINT_ARGUMENTS
1141+
#include "llvm/IR/IntrinsicImpl.inc"
1142+
#undef GET_INTRINSIC_PRETTY_PRINT_ARGUMENTS

0 commit comments

Comments
 (0)