https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119832

            Bug ID: 119832
           Summary: RISC-V: Redundant floating point rounding mode
                    store/restore
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Keywords: missed-optimization
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: kito at gcc dot gnu.org
  Target Milestone: ---
            Target: riscv

How to reproduce:
```shell
$ riscv64-unknown-linux-gnu-gcc  test.cc -S -O3 -march=rv64gcv -ffast-math 
```

Testcase:
```c++
struct ac  {
  ~ac();
  void u();
};
struct ae {
  int s;
  float *ag;
};

float c;

void ak(ae *al, int n) {
  ac d;
  for (int i;i<n;++i) {
    float a = 0;
    for (long j; j < al[i].s; j++)
      a += al[i].ag[j];
    c = a;
    d.u();
  }
}
```

Generated asm (simplified):
```asm
_Z2akP2aei:
...
    frrm    a5
...
    fsrm    a5 ; No one really change a5 any where,
               ; and no static rounding mode instruction at all
... 
...
    frrm    a5
```


Symptom:

There is no static rounding mode in the function, but we still decide back up
and restore the floating point rounding mode register, we could drop the back
up and restore instruction in theory.


Why:

There is a basic block has two in edge, one with FRM_DYN_CALL and and one with
FRM_DYN, it made the gcc feel the mode is unknown status so become FRM_NONE.

And it seems like because there is some abnormal edge that disturb some
thing...


Possible Solution:

I found a target hook called TARGET_MODE_CONFLUENCE, that can merge two
different mode and return a merged mode, that seems can resolve this issue, but
not sure if it's right direction.

Reply via email to