Hi, I can print an operation easily and get something like %0 = Actor.DoSomething %1 %2
. However, I find it difficult to print the results and operands, separately. For example, for debugging purposes, I would like to print %0
at one place and %1 %2
at another place. I tried to use Value::printAsOperand() but it doesn’t work out (I guess that I’m not using AsmState in a correct way). In LLVM, there is Value::getName(). I’m wondering if MLIR has a similar function to do so? Thanks!
Value naming is kind of nuanced, because the way a value gets named can depend on a lot of factors: are you printing with local scope? are you printing in the generic form? what is the top-level operation you are printing under? does something override the interface for providing names? etc. Each of those can change the end result, and many of those can be dynamic (i.e. be different on different calls to print).
MLIR values do not inherently have names, as they do in LLVM, so we don’t provide any type of getName functionality. The reasons for this are varied, and some of it has to do with things mentioned above.
AsmState should be the source of truth for how naming is done (the non-AsmState print functions just construct one internally and call into the AsmState variants). Can you share what setup you are using?
Thanks for the heads up that the naming is dynamic. I was able to reproduce what I would like to retrieve from the AsmPrinter.
Hi there!
Would you mind sharing how exactly you managed this ?
I am looking for a “reliable” way to erase an operation if it doesn’t use any of a set of operands (with specific names). So I want to compare the operand names of each operation with those in my set.
This seems kind of a gamble given that the names can change frequently, but I can’t think of another way.
Thanks in advance!
Could you expand on your use case? Is only condition for deleting operand name/how are those names determined?
I am working with CIRCT,
A user specifies which ports ( or registers or wires etc.) are important in a Chisel HDL design. Currently this is just done as a string in a JSON file. I am writing a pass to strip all operations from the mlir representation of the design, except those that use these named variables. Some transformations are done to the names of the ports when lowering to mlir, but they seem to stay relatively consistent…
So yes, currently just the names of the values and the modules where they are found are used as conditions.
For this use case, I think you can map from the port names you have explicitly without comparing to the name given to SSA values in the textual IR. The CIRCT operations for the modules you are looking at will have attributes that contain the names of each port, and there are APIs that should allow you to map from a port name to the corresponding SSA value.
Yes, you are right! I was iterating through .getAllPorts()
to get the port names and then indexing the module Operation with the index of the port, to get the operand. However I don’t think this is applicable for regs and other assignments within the module (i.e. vals that aren’t ports)
I found that declaring vals in Chisel such as:
val x = Reg(UInt())
produces a verilogName
attribute which I can compare to:
%x = sv.reg {hw.verilogName = "x"} : !hw.inout<i16>
would this be a reliable attribute to use ?
I am new to a lot of this ! so I don’t know what attributes are ephemeral when converting between dialects… Not sure what to trust
If you have questions about this sort of thing, it might be worth asking on the CIRCT topic, since the folks who know CIRCT will answer there.
But to answer this specific question, named declarations will generally have a name
attribute corresponding to the name of the val in Chisel. The hw.verilogName
attribute should generally be present at the end of the pipeline as well, and corresponds to the actual name emitted into Verilog. This deals with name collisions, reserved words, etc.
Thank you! Much appreciated
And yes, I will shift over to the CIRCT topic