Add freeze to fmul and other instruction rules
- Dominant language
- LLVM
- Stars
- 1.7k
- Forks
- 188
- Avg merge
- 2d 4h
- Merged PRs (30d)
- 22
Description
https://fwd.gymni.ch/0IYvt2
See the reverse rule above.
```llvm
define double @square(double %arg) {
; arg, 1
%i8 = insertelement <2 x double> , double %arg, i32 0
; arg undef, arg
%i12 = fmul <2 x double> , %i8
; arg
%i14 = extractelement <2 x double> %i12, i32 1
ret double %i14
}
```
This generates the code:
```llvm
define internal { double } @diffesquare(double %arg, double %differeturn) #0 {
%"i12'de" = alloca <2 x double>, align 16
store <2 x double> zeroinitializer, <2 x double>* %"i12'de", align 16
br label %invert
invert: ; preds = %0
%1 = getelementptr inbounds <2 x double>, <2 x double>* %"i12'de", i64 0, i64 1
%2 = load double, double* %1, align 8
%3 = fadd fast double %2, %differeturn
store double %3, double* %1, align 8
%4 = load <2 x double>, <2 x double>* %"i12'de", align 16
%m1diffei8 = fmul fast <2 x double> %4,
store <2 x double> zeroinitializer, <2 x double>* %"i12'de", align 16
%5 = fadd fast <2 x double> zeroinitializer, %m1diffei8
%6 = extractelement <2 x double> %5, i32 0
%7 = fadd fast double 0.000000e+00, %6
%8 = insertvalue { double } undef, double %7, 0
ret { double } %8
}
```
Propagating back from extractelem you get a shadow of <0.0, diffret>
This then propagates <0.0, diffret> * to its operand of <%arg, 1.0>.
If 0.0 dominates then this correctly means shadow(arg) += 0.
However if the 0.0 doesn't dominate (say if it's poison) then undef * 0 -> undef, and thus shadow(arg) += undef -> derivative = undef.
Using freeze on the operand to the fmul would ensure the correct result in this instance since then it would ensure 0 * freeze(...) -> 0. Alternatively we could do say `if dx=0, 0, else, dx*y`
Contributor guide
Assessment
This issue has not been assessed yet.