On querying an Operation's intrinsic (core) vs external/user-defined attributes

This whole topic is quite related to the design of LLVM metadata which hasn’t aged well. You have three basic policies that you can put into canonicalizations and folds when you encounter “extra info” on nodes that you’re working with:

  1. block the transformation
  2. implicitly drop the metadata
  3. implicitly propagate

The right answer depends on the metadata in question. If you have attrs that changes the semantics of the nodes in question or which is required to be propagated for correctness, then #1 is generally the right thing to do.

If you don’t know anything about the metadata, #2 is the conservatively correct thing (this is what MLIR does, and what LLVM does for its metadata). This is important because there are many different kinds of canonicalizations (for example) including ones that walk up the SSA graph and change “used” operations: e.g. strength reducing an operand because you know the only user doesn’t need all the bits being produced. These sorts of transformations scramble “arbitrary unknown” metadata because the properties they reflect may not hold anymore.

The “implicitly propagate” policy can make sense for certain kinds of things - for example, if you’re trying to propagate hints about loop performance (rolls a lot, rolls only a few times, etc) then it can be useful to carry them forward as loops are transformed. The problem with this though is that you can’t differentiate between friendly and unfriendly to propagate metadata.

As a consequence of this, we implicitly drop out of conservatism (we aren’t perfect about this though - eg when nodes are mutated in place). We’ve discussed multiple times that it would be possible to make a scheme for attributes to help differentiate between the cases, but no one has had time or interest in baking out that model. It is also very difficult and nuanced to do.

-Chris