The CallOpInterface has an interface method to distinguish between operands that are passed to the callee (“forwarded operands”) and other operands:
InterfaceMethod<[{
Returns the operands within this call that are used as arguments to the
callee.
}],
"::mlir::Operation::operand_range", "getArgOperands"
>,
First observation: There is no corresponding interface method for results.
Now on to verification. The CallOpInterface does not verify that:
- The number of forwarded operands matches the number of arguments of the callee.
- The types of the forwarded operands match the argument types of the callee.
For (2) there is precedent in other interfaces (e.g. BranchOpInterface::areTypesCompatible). Existing transformations for CallOpInterface either bail on a type mismatch or build a conversion (e.g. DialectInlinerInterface::materializeCallConversion).
Case (1) seems a bit fishy to me. The absence of this verifier check suggests that the number of caller operands and callee arguments may not necessarily match. Then why do we have getArgOperands in the first place? Even worse: Even if the count matches, can we safely assume that operand i is passed as argument i? (Probably yes, but it’s not documented anywhere.) Maybe the semantics of the concrete call op are such that the callee receives the forwarded values in inverse order. In such a case, the inliner implementation would be incorrect.
(Note: Concrete ops like func.func perform more verification, but many transformations and analyses operate on the interface.)
What I would suggest:
- Add a
getProducedResults(orgetForwardedResults) interface method toCallOpInterface, so that the interface can distinguish between forwarded and produced results. (This will make result handling symmetric to operand handling.) - Verify that the number of forwarded operands (as per
getArgOperands) matches the number arguments of the callee. - Verify that the number of forwarded results (as per
getForwardedResults) matches the number of results of the callee. - Document that the forwarded operands are in a 1:1 relationship with the callee arguments. I.e.
i-th forwarded operand corresponds toi-th argument. (However, the type can be different.) Same for results. - Optional: Add a new interface method
CallOpInterface::areTypesCompatiblewith a default implementation ofreturn true.
Any thoughts?