[clang] Always honor fp-contract pragmas on PlayStation (PR #162549)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Oct 8 13:57:47 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-x86
Author: None (wjristow)
<details>
<summary>Changes</summary>
The pragma:
#pragma clang fp contract (off)
can be used to disable FMA, but when cross-statement FMA is enabled in `fast` fp contract mode (via `-ffast-math`, for example), the effect of that pragma is suppressed.
To have Clang honor that pragma in 'fast' fp contract mode in C/C++, an additional switch:
-ffp-contract=fast-honor-pragmas
must be applied. On PlayStation, we want to always honor that pragma, without requiring the additional switch to be specified. This commit does that.
---
Full diff: https://github.com/llvm/llvm-project/pull/162549.diff
2 Files Affected:
- (modified) clang/lib/CodeGen/BackendUtil.cpp (+5-1)
- (added) clang/test/CodeGen/X86/fma-fast-pragma.cpp (+53)
``````````diff
diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp
index 64f1917739e12..52bf702cdadb0 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -396,7 +396,11 @@ static bool initTargetOptions(const CompilerInstance &CI,
Options.AllowFPOpFusion = llvm::FPOpFusion::Standard;
break;
case LangOptions::FPM_Fast:
- Options.AllowFPOpFusion = llvm::FPOpFusion::Fast;
+ // We always honor fp-contract pragmas for PlayStation.
+ if (CI.getASTContext().getTargetInfo().getTriple().isPS())
+ Options.AllowFPOpFusion = llvm::FPOpFusion::Standard;
+ else
+ Options.AllowFPOpFusion = llvm::FPOpFusion::Fast;
break;
}
diff --git a/clang/test/CodeGen/X86/fma-fast-pragma.cpp b/clang/test/CodeGen/X86/fma-fast-pragma.cpp
new file mode 100644
index 0000000000000..9d38e245b5f64
--- /dev/null
+++ b/clang/test/CodeGen/X86/fma-fast-pragma.cpp
@@ -0,0 +1,53 @@
+// REQUIRES: x86-registered-target
+
+// With the pragma in place, generic targets leave FMA enabled unless the
+// switch '-ffp-contract=fast-honor-pragmas' is used to disable it; whereas
+// for PlayStation, the pragma is always honored, so FMA is disabled even in
+// plain 'fast' mode:
+// RUN: %clang_cc1 -S -triple x86_64-unknown-unknown -target-feature +fma \
+// RUN: -O2 -ffp-contract=fast -o - %s | \
+// RUN: FileCheck --check-prefix=CHECK-YES-FMA %s
+// RUN: %clang_cc1 -S -triple x86_64-unknown-unknown -target-feature +fma \
+// RUN: -O2 -ffp-contract=fast-honor-pragmas -o - %s | \
+// RUN: FileCheck --check-prefix=CHECK-NO-FMA %s
+// RUN: %clang_cc1 -S -triple x86_64-unknown-unknown -target-feature +fma \
+// RUN: -O2 -ffp-contract=fast -ffp-contract=fast-honor-pragmas -o - %s | \
+// RUN: FileCheck --check-prefix=CHECK-NO-FMA %s
+// RUN: %clang_cc1 -S -triple x86_64-sie-ps5 -target-feature +fma \
+// RUN: -O2 -ffp-contract=fast -o - %s | \
+// RUN: FileCheck --check-prefix=CHECK-NO-FMA %s
+// RUN: %clang_cc1 -S -triple x86_64-sie-ps5 -target-feature +fma \
+// RUN: -O2 -ffp-contract=fast-honor-pragmas -o - %s | \
+// RUN: FileCheck --check-prefix=CHECK-NO-FMA %s
+//
+// With the pragma suppressed, FMA happens in 'fast' or 'fast-honor-pragmas'
+// modes (for generic targets and for PlayStation):
+// RUN: %clang_cc1 -S -DSUPPRESS_PRAGMA \
+// RUN: -triple x86_64-unknown-unknown -target-feature +fma \
+// RUN: -O2 -ffp-contract=fast -o - %s | \
+// RUN: FileCheck --check-prefix=CHECK-YES-FMA %s
+// RUN: %clang_cc1 -S -DSUPPRESS_PRAGMA \
+// RUN: -triple x86_64-unknown-unknown -target-feature +fma \
+// RUN: -O2 -ffp-contract=fast-honor-pragmas -o - %s | \
+// RUN: FileCheck --check-prefix=CHECK-YES-FMA %s
+// RUN: %clang_cc1 -S -DSUPPRESS_PRAGMA \
+// RUN: -triple x86_64-sie-ps5 -target-feature +fma \
+// RUN: -O2 -ffp-contract=fast -o - %s | \
+// RUN: FileCheck --check-prefix=CHECK-YES-FMA %s
+// RUN: %clang_cc1 -S -DSUPPRESS_PRAGMA \
+// RUN: -triple x86_64-sie-ps5 -target-feature +fma \
+// RUN: -O2 -ffp-contract=fast-honor-pragmas -o - %s | \
+// RUN: FileCheck --check-prefix=CHECK-YES-FMA %s
+//
+float compute(float a, float b, float c) {
+#if !defined(SUPPRESS_PRAGMA)
+#pragma clang fp contract (off)
+#endif
+ float product = a * b;
+ return product + c;
+}
+
+// CHECK-NO-FMA: vmulss
+// CHECK-NO-FMA-NEXT: vaddss
+
+// CHECK-YES-FMA: vfmadd213ss
``````````
</details>
https://github.com/llvm/llvm-project/pull/162549
More information about the cfe-commits
mailing list