syntacore / snippy

Other
43 stars 4 forks source link

Facilities to stop NaN propagation in FPU programs #11

Closed kv-sc closed 1 month ago

kv-sc commented 5 months ago

Reproduce on 1.0

snippy command line:

./llvm-snippy -march=riscv64-linux-gnu -mattr="+f,+d" -reserved-regs-list="F0_D,F1_D,F2_D,F3_D,F4_D,F5_D,F6_D,F7_D,F8_D,F9_D,F13_D,F14_D,F15_D,F16_D,F17_D,F18_D,F19_D,F20_D,F21_D,F22_D,F23_D,F24_D,F25_D,F26_D,F27_D,F28_D,F29_D,F30_D,F31_D,X3,X4" -num-instrs=1000 -seed=0 -model-plugin=None ./layout-stack.yaml --init-regs-in-elf -last-instr=RET --honor-target-abi --external-stack

where layout-stack.yaml looks like:

sections:
  - no:        0
    VMA:       0x200000
    SIZE:      0x10000
    LMA:       0x200000
    ACCESS:    r
  - no:        1
    VMA:       0x210000
    SIZE:      0x100000
    LMA:       0x210000
    ACCESS:    rx
  - no:        2
    VMA:       0x400000
    SIZE:      0x100000
    LMA:       0x400000
    ACCESS:    rw

call-graph:
  entry-point: SnippyFunction
  function-list:
    - name: SnippyFunction
      callees:
        - myfunc
    - name: myfunc
      external: true

histogram:
     - [FADD_D, 3.0]
     - [FDIV_D, 3.0]
     - [FMUL_D, 3.0]
     - [FSUB_D, 3.0]
     - [JAL, 1.0]

file myfunc.c:

#include <stdio.h>

void SnippyFunction();

int main() {
  SnippyFunction();
}

void myfunc(double a, double b, double c) {
  printf("%lf, %lf, %lf\n", a, b, c);
}

Link:

riscv64-unknown-linux-gnu-gcc layout-stack.yaml.elf myfunc.c --static

Run:

qemu-riscv64 ./a.out

You will see all NaN's from some moment:

0.000000, 40218038886127496574296745899399669469321707570122526914569185871875156215437721600.000000, -138045858897988964649892385629183438148452756182408624093268872718730204601415295754909095360179370021264444269979234186020103682241025079447796987457768435325337600.000000
-138045858897988964649892385629183438148452756182408624093268872718730204601415295754909095360179370021264444269979234186020103682241025079447796987457768435325337600.000000, 40218038886127496574296745899399669469321707570122526914569185871875156215437721600.000000, -138045858897988964649892385629183438148452756182408624093268872718730204601415295754909095360179370021264444269979234186020103682241025079447796987457768435325337600.000000
0.000000, -5551933721228190040891410660573517160096470692414526918920611429325881414518518172311287619687182300040152711520452995236828182756607735946804109994190053157736295687726783280742427698719907518737640118245085691142791819310348625796764153805799424.000000, 1.000000
1.000000, 1.000000, -0.000000
nan, nan, nan
nan, nan, nan
nan, nan, nan
nan, nan, nan
nan, nan, nan
nan, nan, nan
nan, nan, nan
nan, nan, nan
nan, nan, nan
nan, nan, nan
nan, nan, nan
nan, nan, nan
nan, nan, nan
....
arrv-sc commented 1 month ago

Fixed in https://github.com/syntacore/snippy/pull/68

New yaml keys were introduced to configure NaN-controlling behavior. Example:

fpu-config: 
  overwrite: 
    range: 
      min: -1000
      max:  1000
    heuristic: if-all-operands

You can specify the range of values that will be used for overwriting NANs. These values can only be integers for now.

You can also specify heuristic that tells how to determine that register holds NAN. Currently there are 2 possible values for heuristic: "if-all-operands" – We consider register a NAN if all of his input registers are potentially NANs "if-any-operand" – We consider register a NAN if any of his input registers are potentially NANs

Full potential configuration:

histogram: 
  - [FDIV_D, 1.0]
  - [FMUL_D, 1.0]
sections: 
  - no:        1
    VMA:       0x210000
    SIZE:      0x100000
    LMA:       0x210000
    ACCESS:    rx
  - no:        2
    VMA:       0x100000
    SIZE:      0x100000
    LMA:       0x100000
    ACCESS:    rw
fpu-config: 
  overwrite: 
    range: 
      min: -1000
      max:  1000
    heuristic: if-all-operands