Canonicalization passes don't keep attributes

On that second thread, I proposed two concrete things – both accessors or simple API additions but the discussion veered in the direction of higher-level principles. Repasting from there: these are only utilities/tools to solve this problem and I feel generally useful even if we don’t change any upstream passes.

  1. On querying an Operation's intrinsic (core) vs external/user-defined attributes - #20 by bondhugula
    “… it’d be useful to have these two accessors auto-generated on an op:”
void getExternalAttributes(SmallVectorImpl<Attribute> &attrs);
void getIntrinsicAttributes(SmallVectorImpl<Attribute> &attrs);

Both can be auto-generated on a derived op OpTy.

  1. On querying an Operation's intrinsic (core) vs external/user-defined attributes - #21 by bondhugula
    rewriter.replaceOp can have an optional argument that if true will transparently propagate all external attributes using getExternalAttributes to the new op. This will be useful for users typically for the same op type 1:1 replacements.
PatterRewriter::replaceOp(... , ..., bool propagateExtAttrs = false)

That’ll avoid extra trailing lines everywhere and I feel will easily make things consistent. I’m not sure how replaceOpWithNewOp should be updated – perhaps an optional template arg.

rewriter.replaceOpWithNewOp<newOpTy, /*propagateExtAttrs=*/true>(....)