[Discuss] Is constant division-to-multiplication rewrite in TVM necessary?

I came across the following rewrite rule in the simplifier:

// In RewriteSimplifier::Impl::VisitExpr_(const DivNode* op)
if (const FloatImmNode* ptr = op->b.as<FloatImmNode>()) {
  ICHECK(op->dtype.is_float() || op->dtype.is_bfloat16() ||
         datatype::Registry::Global()->GetTypeRegistered(op->dtype.code()));
  return op->a * make_const(op->b.dtype(), 1.0 / ptr->value);
}

From my understanding, this transforms a floating‑point constant division

a / const

into a multiplication by its reciprocal:

a * (1.0 / const)

presumably for performance reasons.


Question

For floating‑point computations, this rewrite is not always bit‑wise identical, since multiplication and division may follow different rounding paths and use different intermediate representations.

This means that, for certain workloads, developers may find that the program’s output is not bit‑identical to what they expected.

Should we consider adding a flag to disable such simplifications? Or is this generally not a significant issue, as long as a kernel’s output remains deterministic?

This is a good point. Original motivation was perf. However, after thinking a bit more, i think such pattern is a bit more rare now, to simplify things, maybe we can remove this rule

1 Like

@LeiWang1999 can u send a PR?

related pr: [TIR] Refactor division simplification in RewriteSimplifier by LeiWang1999 · Pull Request #18319 · apache/tvm · GitHub

But I think we should have a further discussion, because some of the constant‑folding and algebraic rewrites may also introduce similar issues. Examples include:

  • (x * c1) * c2 → x * (c1 * c2)
  • (x / c1) / c2 → x / (c1 * c2) (with correct division semantics)
  • (x * c1) / c2 simplified if c1 divisible by c2, or vice versa.
  • (x / c1) + c2 normalized into a single division when possible.
  • (y + z) * x → y * x + z * x
  • (x + c1) * c2 → x * c2 + c1 * c2
  • y*x + z*x → (y+z) * x

However, these rewrites are important for optimization and performance, I think we should consider introducing a deterministic switch or similar option that can disable these transformations when strict, this pr should be closed.

We will indeed needs these opertaionts for integers. One thing we can do is to disable them for floats, or introduce a flag like you suggested to disable for floats.

I believe for many rules you mentioned they are already only enabled for integers

For example tvm/src/arith/rewrite_simplify.cc at main · apache/tvm · GitHub