Issue 140491
Summary Incorrect code-gen with stack-slot sharing for `sincos` results
Labels new issue
Assignees
Reporter wjristow
    We have encountered a miscompile where stack-slot sharing is incorrect for the results of:

`void sincosf(float x, float *sin, float *cos);`

I've bisected it to [llvmorg-20-init-6824-g3073c3c2290a](https://github.com/llvm/llvm-project/commit/3073c3c2290a6d9b12fbaefa40dd22eef6312895), so this is a regression in llvm20.

Note that a fix for an apparently related issue was made in [PR 118117](https://github.com/llvm/llvm-project/pull/118117) ([llvmorg-20-init-15653-ga7dafea384a5](https://github.com/llvm/llvm-project/commit/a7dafea384a519342b2fbe210ed101c1e67f3be7)), but this problem still persists.

Here is a reduced test-case that shows a run-time failure:
```
extern "C" {
  int printf(const char *, ...);
 float cosf(float);
  float sinf(float);
  float fabsf(float);
}
int n_errors = 0;

__attribute__((noinline))
void CheckClose(float &computed, float &expected, float &tolerance, int lnum) {
  float diff = fabsf(computed - expected);
  if (diff >= tolerance) {
    printf("Expected  %f +/ %f but was %f (failure on line %d)\n",
           expected, tolerance, computed, lnum);
    ++n_errors;
  } else {
    printf("Expected  %f +/ %f and was %f\n", expected, tolerance, computed);
  }
}

float input_value = 0.33981341f;
float expected_pos_cos =  0.94281685f;
float expected_neg_cos = -0.94281685f;
float expected_neg_sin = -0.33331117f;

int main() {
 float value = input_value;            // 0.33981341f (input)
  float local_cos = ::cosf(value);      // 0.94281685f (computed)
  float local_sin = ::sinf(value);      // 0.33331117f (computed)
  float close = 0.000010f;
 {
    float computed = local_cos;
    float expected = expected_pos_cos;
 CheckClose(computed, expected, close, __LINE__);
  }
  {
    float computed = -local_sin;
    float expected = expected_neg_sin;
 CheckClose(computed, expected, close, __LINE__);
  }
  {
    float computed = -local_cos; // 0.33331117f is passed, expected -0.94281685f
 float expected = expected_neg_cos;
    CheckClose(computed, expected, close, __LINE__);
  }
  printf("%d error(s).  %s\n", n_errors, ((n_errors == 0) ? "PASS" : "FAIL"));
}
```
The problem only manifests (for me at least) when `cosf` and `sinf` are turned into builtins.  That happens with the PS5 target (and PS4), but it doesn't happen for me with the target `x86_64-unknown-linux-gnu`.  So to see the run-time failure in a godbolt link, starting with C++ source doesn't demonstrate it.  So I'm posting an [llvm IR godbolt link](https://godbolt.org/z/M697bqGxb) that processes the IR at `-O2`, and shows the run-time failure.

Note that dropping `has-predecessor-max-steps` ("llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp") to a low number (the default is 8192) suppresses the transformation, and so hides the failure. Using the current head of `main`, dropping it to 13:
`-O2 -mllvm -has-predecessor-max-steps=13`
makes the problem latent.

The problem is still there in the head of `main` (tested with [llvmorg-21-init-12399-gc78e6bbd830a](https://github.com/llvm/llvm-project/commit/c78e6bbd830a4633fa7c80aebb9680b6acf913c6)).
_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to