This is a followup of https://github.com/dmlc/tvm/issues/3478 

## Background: DIvMod Variants
### Trunc div/mod
IEEE standard integer division is truncated division, directly maps to the 
hardware. This is the division used by C and TVM by default. The problem of 
trunc div is that we usually relies on knowing the sign of both operands. For 
example, we cannot simplify ```(x * 4 + 3)/4 => x ``` if x can be negative.

### Floor div/mod
Always round down. This is the division mode adopted by python. To simplify 
floordiv, we usually need to know the sign of divisor, but not necessarily the 
sign of dividend  ```floordiv(x * 4 + 3,4) => x ```. 

### Euclidean div/mod
Always ensures that the remainder is non-negative. This is the division mode 
used by Halide by default. Note that when the divisor is positive, Euclidean 
and floordiv are equivalent. But floordiv will produce a negative remainder 
when the divisor is negative.

##  Challenges of using FloorDiv
FloorDiv/Mod has a better advantage of doing simplifications. The main 
challenge of using FloorDiv/Mod is when we lower the code into low level 
divisions, where we have to make use of trunc div/mod. 

In most cases, when we can prove the positiveness of the divident and divisor, 
we can simply lower the results into truncdiv without problem to get the best 
of efficiency as well as analysis. However, we need be careful about cases 
where these proves fail due to lack of information, and provide these 
information into the IR.

## Example Case of Lowering that Need Developer Attention
```c++
for (i, 0, n) {
    A[floordiv(i, m) * m] = 0 
}
```
Consider the above code. We cannot simply translate ```floordiv(i, m)``` to 
```truncdiv(i, m)``` because we **do not know** that m is non-negative in the 
above IR.

This is however due to lack of additional information provided. In many cases, 
```m``` is intended to be a symbolic shape of a tensor, in which case it is 
supposed to be non-negative. If we have a hint in the code as in below, then we 
will be able to handle it correctly.

```c++
assert m >= 0
for (i, 0, n) {
    A[floordiv(i, m) * m] = 0 
}
``` 

This is something we need to keep in mind especially when we handle cases like 
symbolic shape operations.

## Steps

- [x] Introduce lowering of FloorDiv/Mod
- [ ] Migrate internal index calculations of split/fuse to floordiv
- [ ] Consider remove operator overload of div and mod and force developers to 
use truncdiv or floordiv, so they can be aware of the difference



-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/dmlc/tvm/issues/3977

Reply via email to