llvm / llvm/llvm-project

[X86][Performance][regression] Adding nosync to sqrt causes ~40% SPEC CPU 2017 544.nab_r & 644.nab_s regression on AMD Zen 4

Open
#216,794 1 comment 2 reactions 0 assignees View on GitHub
backend:X86 llvm:transforms optimization:AMDCPU performance regression:23
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

The following two SPEC CPU 2017 tests are showing severe regressions after https://github.com/llvm/llvm-project/pull/197761 landed:

| CPU | Test | Good (s) | Bad (s) | Slowdown | Regression |
|---|---|---:|---:|---:|---:|
| Zen 2 | `544.nab_r` | 75.9950 | 86.9014 | 1.1435× | **+14.35%** |
| Zen 2 | `644.nab_s` | 76.0114 | 86.8487 | 1.1426× | **+14.26%** |
| Zen 4 | `544.nab_r` | 48.92 | 68.48 | 1.3998× | **+39.98%** |
| Zen 4 | `644.nab_s` | 49.03 | 68.30 | 1.3930× | **+39.30%** |

I worked with Codex to try to figure out what is happening in this particular case and it seems like the path that is causing the regression is:

1. nosync added to sqrt
2. GlobalAA now returns NoModRef for sqrt for a global used by the test (global is named `dim` in this case)
3. EarlySCE removes post call loads for this global
4. The loaded value stays live for longer
5. For some reason this causes pathological codegen on Zen4 and still severe but less bad codegen on Zen2

This was verified this by hacking GlobalAA to not return NoModRef for `dim` and the results returned to pre https://github.com/llvm/llvm-project/pull/197761 levels. This is the diff used:

```
diff --git a/llvm/lib/Analysis/GlobalsModRef.cpp b/llvm/lib/Analysis/GlobalsModRef.cpp
index 06d6be91d99f..d4a76f774dc7 100644
--- a/llvm/lib/Analysis/GlobalsModRef.cpp
+++ b/llvm/lib/Analysis/GlobalsModRef.cpp
@@ -952,6 +952,16 @@ ModRefInfo GlobalsAAResult::getModRefInfo(const CallBase *Call,
const MemoryLocation &Loc,
AAQueryInfo &AAQI) {
ModRefInfo Known = ModRefInfo::ModRef;
+
+ if (const auto *GV =
+ dyn_cast(getUnderlyingObject(Loc.Ptr))) {
+ if (GV->hasLocalLinkage() && GV->getName() == "dim") {
+ if (const Function *F = Call->getCalledFunction()) {
+ if (F->isDeclaration() && F->getName() == "sqrt")
+ return ModRefInfo::ModRef;
+ }
+ }
+ }

// If we are asking for mod/ref info of a direct call with a pointer to a
// global we are tracking, return information if we have it.

```

Contributor guide

Open the contributing guide

Research direction

Start in llvm/lib/Analysis/GlobalsModRef.cpp at GlobalsAAResult::getModRefInfo and compare the behavior introduced by pull request 197761. Reproduce the 544.nab_r and 644.nab_s SPEC CPU 2017 regressions on Zen 2 or Zen 4, then verify that the regression is removed without undoing the intended nosync change.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
compilers, performance
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.