I finally figured out why. @junrushao @yuchenj
AnnotateSpans is to add span information to an IR. However, its implementation is very simple:
- print current IR using
AsTextand - parse it again to obtain span information.
Since when printing an IRModule it is ill-formed to have variables in the same names, when calling AsText, GetUniqueName will be applied to modified in-memory names to some other names making sure that the whole printed IR do not have identical variable names. For example, if that current IR has 2 functions whose parameters are both “p0”. AsText will rename one of them like “p01”.
Hence, step 1 of AnnotateSpans might change the name of variables. And Step 2 (parsing) directly read those variables with their new names, breaking original information about their old names which might contain some kind of information itself (e.g., FuseOps). And this is the root cause making AnnotateSpans incompatible with passes like DefuseOps which looks at the variable name:
Expr VisitExpr_(const VarNode* n) {
const std::string& name = n->name_hint();
ICHECK(!name.empty() && (name[0] == 'p')); // <--- `AnnotateSpans` breaks the name so that things become illegal!
std::string id_str = name.substr(1);
int id = std::stoi(id_str);
ICHECK(id >= 0 && size_t(id) < args_.size());
return args_[id];
}
A quick fix is to record a reverse mapping when GetUniqueName changes the names (new_name → old_name). And after applying step 1&2, we resume the names of the new IR module through renaming.
Also thanks for the help from @merrymercy