Skip to content

Commit 9e1b410

Browse files
committed
Always honor fp-contract pragmas on PlayStation
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.
1 parent 497d648 commit 9e1b410

File tree

2 files changed

+58
-1
lines changed

2 files changed

+58
-1
lines changed

clang/lib/CodeGen/BackendUtil.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,11 @@ static bool initTargetOptions(const CompilerInstance &CI,
396396
Options.AllowFPOpFusion = llvm::FPOpFusion::Standard;
397397
break;
398398
case LangOptions::FPM_Fast:
399-
Options.AllowFPOpFusion = llvm::FPOpFusion::Fast;
399+
// We always honor fp-contract pragmas for PlayStation.
400+
if (CI.getASTContext().getTargetInfo().getTriple().isPS())
401+
Options.AllowFPOpFusion = llvm::FPOpFusion::Standard;
402+
else
403+
Options.AllowFPOpFusion = llvm::FPOpFusion::Fast;
400404
break;
401405
}
402406

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// REQUIRES: x86-registered-target
2+
3+
// With the pragma in place, generic targets leave FMA enabled unless the
4+
// switch '-ffp-contract=fast-honor-pragmas' is used to disable it; whereas
5+
// for PlayStation, the pragma is always honored, so FMA is disabled even in
6+
// plain 'fast' mode:
7+
// RUN: %clang_cc1 -S -triple x86_64-unknown-unknown -target-feature +fma \
8+
// RUN: -O2 -ffp-contract=fast -o - %s | \
9+
// RUN: FileCheck --check-prefix=CHECK-YES-FMA %s
10+
// RUN: %clang_cc1 -S -triple x86_64-unknown-unknown -target-feature +fma \
11+
// RUN: -O2 -ffp-contract=fast-honor-pragmas -o - %s | \
12+
// RUN: FileCheck --check-prefix=CHECK-NO-FMA %s
13+
// RUN: %clang_cc1 -S -triple x86_64-unknown-unknown -target-feature +fma \
14+
// RUN: -O2 -ffp-contract=fast -ffp-contract=fast-honor-pragmas -o - %s | \
15+
// RUN: FileCheck --check-prefix=CHECK-NO-FMA %s
16+
// RUN: %clang_cc1 -S -triple x86_64-sie-ps5 -target-feature +fma \
17+
// RUN: -O2 -ffp-contract=fast -o - %s | \
18+
// RUN: FileCheck --check-prefix=CHECK-NO-FMA %s
19+
// RUN: %clang_cc1 -S -triple x86_64-sie-ps5 -target-feature +fma \
20+
// RUN: -O2 -ffp-contract=fast-honor-pragmas -o - %s | \
21+
// RUN: FileCheck --check-prefix=CHECK-NO-FMA %s
22+
//
23+
// With the pragma suppressed, FMA happens in 'fast' or 'fast-honor-pragmas'
24+
// modes (for generic targets and for PlayStation):
25+
// RUN: %clang_cc1 -S -DSUPPRESS_PRAGMA \
26+
// RUN: -triple x86_64-unknown-unknown -target-feature +fma \
27+
// RUN: -O2 -ffp-contract=fast -o - %s | \
28+
// RUN: FileCheck --check-prefix=CHECK-YES-FMA %s
29+
// RUN: %clang_cc1 -S -DSUPPRESS_PRAGMA \
30+
// RUN: -triple x86_64-unknown-unknown -target-feature +fma \
31+
// RUN: -O2 -ffp-contract=fast-honor-pragmas -o - %s | \
32+
// RUN: FileCheck --check-prefix=CHECK-YES-FMA %s
33+
// RUN: %clang_cc1 -S -DSUPPRESS_PRAGMA \
34+
// RUN: -triple x86_64-sie-ps5 -target-feature +fma \
35+
// RUN: -O2 -ffp-contract=fast -o - %s | \
36+
// RUN: FileCheck --check-prefix=CHECK-YES-FMA %s
37+
// RUN: %clang_cc1 -S -DSUPPRESS_PRAGMA \
38+
// RUN: -triple x86_64-sie-ps5 -target-feature +fma \
39+
// RUN: -O2 -ffp-contract=fast-honor-pragmas -o - %s | \
40+
// RUN: FileCheck --check-prefix=CHECK-YES-FMA %s
41+
//
42+
float compute(float a, float b, float c) {
43+
#if !defined(SUPPRESS_PRAGMA)
44+
#pragma clang fp contract (off)
45+
#endif
46+
float product = a * b;
47+
return product + c;
48+
}
49+
50+
// CHECK-NO-FMA: vmulss
51+
// CHECK-NO-FMA-NEXT: vaddss
52+
53+
// CHECK-YES-FMA: vfmadd213ss

0 commit comments

Comments
 (0)