Skip to content

Commit 72c373b

Browse files
[C++17] Support __GCC_[CON|DE]STRUCTIVE_SIZE (#89446)
These macros are used by STL implementations to support implementation of std::hardware_destructive_interference_size and std::hardware_constructive_interference_size Fixes #60174 --------- Co-authored-by: Louis Dionne <[email protected]>
1 parent 0620a63 commit 72c373b

File tree

24 files changed

+181
-38
lines changed

24 files changed

+181
-38
lines changed

clang-tools-extra/test/pp-trace/pp-trace-pragma-general.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ void foo() {
2121

2222
// CHECK: ---
2323
// CHECK-NEXT: - Callback: PragmaDirective
24+
// CHECK-NEXT: Loc: "<built-in>:{{.+}}:1"
25+
// CHECK-NEXT: Introducer: PIK_HashPragma
26+
// CHECK-NEXT: - Callback: PragmaDirective
27+
// CHECK-NEXT: Loc: "<built-in>:{{.+}}:1"
28+
// CHECK-NEXT: Introducer: PIK_HashPragma
29+
// CHECK-NEXT: - Callback: PragmaDirective
2430
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-general.cpp:3:1"
2531
// CHECK-NEXT: Introducer: PIK_HashPragma
2632
// CHECK-NEXT: - Callback: PragmaDiagnosticPush

clang-tools-extra/test/pp-trace/pp-trace-pragma-ms.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@
1818

1919
// CHECK: ---
2020
// CHECK-NEXT: - Callback: PragmaDirective
21+
// CHECK-NEXT: Loc: "<built-in>:{{.+}}:1"
22+
// CHECK-NEXT: Introducer: PIK_HashPragma
23+
// CHECK-NEXT: - Callback: PragmaDirective
24+
// CHECK-NEXT: Loc: "<built-in>:{{.+}}:1"
25+
// CHECK-NEXT: Introducer: PIK_HashPragma
26+
// CHECK-NEXT: - Callback: PragmaDirective
2127
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-ms.cpp:3:1"
2228
// CHECK-NEXT: Introducer: PIK_HashPragma
2329
// CHECK-NEXT: - Callback: PragmaComment
@@ -67,7 +73,7 @@
6773
// CHECK-NEXT: Introducer: PIK_HashPragma
6874
// CHECK-NEXT: - Callback: PragmaMessage
6975
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-ms.cpp:13:9"
70-
// CHECK-NEXT: Namespace:
76+
// CHECK-NEXT: Namespace:
7177
// CHECK-NEXT: Kind: PMK_Message
7278
// CHECK-NEXT: Str: message argument
7379
// CHECK-NEXT: - Callback: PragmaDirective

clang-tools-extra/test/pp-trace/pp-trace-pragma-opencl.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@
66

77
// CHECK: ---
88
// CHECK-NEXT: - Callback: PragmaDirective
9+
// CHECK-NEXT: Loc: "<built-in>:{{.+}}:1"
10+
// CHECK-NEXT: Introducer: PIK_HashPragma
11+
// CHECK-NEXT: - Callback: PragmaDirective
12+
// CHECK-NEXT: Loc: "<built-in>:{{.+}}:1"
13+
// CHECK-NEXT: Introducer: PIK_HashPragma
14+
// CHECK-NEXT: - Callback: PragmaDirective
915
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-opencl.cpp:3:1"
1016
// CHECK-NEXT: Introducer: PIK_HashPragma
1117
// CHECK-NEXT: - Callback: PragmaOpenCLExtension

clang/docs/LanguageExtensions.rst

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5572,3 +5572,25 @@ but the expression has no runtime effects.
55725572
Type- and value-dependent expressions are not supported yet.
55735573
55745574
This facility is designed to aid with testing name lookup machinery.
5575+
5576+
Predefined Macros
5577+
=================
5578+
5579+
`__GCC_DESTRUCTIVE_SIZE` and `__GCC_CONSTRUCTIVE_SIZE`
5580+
------------------------------------------------------
5581+
Specify the mimum offset between two objects to avoid false sharing and the
5582+
maximum size of contiguous memory to promote true sharing, respectively. These
5583+
macros are predefined in all C and C++ language modes, but can be redefined on
5584+
the command line with ``-D`` to specify different values as needed or can be
5585+
undefined on the command line with ``-U`` to disable support for the feature.
5586+
5587+
**Note: the values the macros expand to are not guaranteed to be stable. They
5588+
are are affected by architectures and CPU tuning flags, can change between
5589+
releases of Clang and will not match the values defined by other compilers such
5590+
as GCC.**
5591+
5592+
Compiling different TUs depending on these flags (including use of
5593+
``std::hardware_constructive_interference`` or
5594+
``std::hardware_destructive_interference``) with different compilers, macro
5595+
definitions, or architecture flags will lead to ODR violations and should be
5596+
avoided.

clang/docs/ReleaseNotes.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,18 @@ C++14 Feature Support
9595
- Sized deallocation is enabled by default in C++14 onwards. The user may specify
9696
``-fno-sized-deallocation`` to disable it if there are some regressions.
9797

98+
C++17 Feature Support
99+
^^^^^^^^^^^^^^^^^^^^^
100+
- Clang now exposes ``__GCC_DESTRUCTIVE_SIZE`` and ``__GCC_CONSTRUCTIVE_SIZE``
101+
predefined macros to support standard library implementations of
102+
``std::hardware_destructive_interference_size`` and
103+
``std::hardware_constructive_interference_size``, respectively. These macros
104+
are predefined in all C and C++ language modes. The values the macros
105+
expand to are not stable between releases of Clang and do not need to match
106+
the values produced by GCC, so these macros should not be used from header
107+
files because they may not be stable across multiple TUs (the values may vary
108+
based on compiler version as well as CPU tuning). #GH60174
109+
98110
C++20 Feature Support
99111
^^^^^^^^^^^^^^^^^^^^^
100112

clang/include/clang/Basic/TargetInfo.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include <cassert>
4141
#include <optional>
4242
#include <string>
43+
#include <utility>
4344
#include <vector>
4445

4546
namespace llvm {
@@ -1792,6 +1793,15 @@ class TargetInfo : public TransferrableTargetInfo,
17921793
/// Whether to support HIP image/texture API's.
17931794
virtual bool hasHIPImageSupport() const { return true; }
17941795

1796+
/// The first value in the pair is the minimum offset between two objects to
1797+
/// avoid false sharing (destructive interference). The second value in the
1798+
/// pair is maximum size of contiguous memory to promote true sharing
1799+
/// (constructive interference). Neither of these values are considered part
1800+
/// of the ABI and can be changed by targets at any time.
1801+
virtual std::pair<unsigned, unsigned> hardwareInterferenceSizes() const {
1802+
return std::make_pair(64, 64);
1803+
}
1804+
17951805
protected:
17961806
/// Copy type and layout related info.
17971807
void copyAuxTarget(const TargetInfo *Aux);

clang/lib/Basic/Targets/ARM.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,10 @@ class LLVM_LIBRARY_VISIBILITY ARMTargetInfo : public TargetInfo {
225225
bool hasBitIntType() const override { return true; }
226226

227227
const char *getBFloat16Mangling() const override { return "u6__bf16"; };
228+
229+
std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {
230+
return std::make_pair(getTriple().isArch64Bit() ? 256 : 64, 64);
231+
}
228232
};
229233

230234
class LLVM_LIBRARY_VISIBILITY ARMleTargetInfo : public ARMTargetInfo {

clang/lib/Basic/Targets/AVR.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,10 @@ class LLVM_LIBRARY_VISIBILITY AVRTargetInfo : public TargetInfo {
175175
std::optional<std::string> handleAsmEscapedChar(char EscChar) const override;
176176
StringRef getABI() const override { return ABI; }
177177

178+
std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {
179+
return std::make_pair(32, 32);
180+
}
181+
178182
protected:
179183
std::string CPU;
180184
StringRef ABI;

clang/lib/Basic/Targets/BPF.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,10 @@ class LLVM_LIBRARY_VISIBILITY BPFTargetInfo : public TargetInfo {
113113
StringRef CPUName(Name);
114114
return isValidCPUName(CPUName);
115115
}
116+
117+
std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {
118+
return std::make_pair(32, 32);
119+
}
116120
};
117121
} // namespace targets
118122
} // namespace clang

clang/lib/Basic/Targets/M68k.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ class LLVM_LIBRARY_VISIBILITY M68kTargetInfo : public TargetInfo {
5656
BuiltinVaListKind getBuiltinVaListKind() const override;
5757
bool setCPU(const std::string &Name) override;
5858
CallingConvCheckResult checkCallingConvention(CallingConv CC) const override;
59+
60+
std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {
61+
return std::make_pair(32, 32);
62+
}
5963
};
6064

6165
} // namespace targets

clang/lib/Basic/Targets/Mips.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,10 @@ class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo {
431431

432432
bool validateTarget(DiagnosticsEngine &Diags) const override;
433433
bool hasBitIntType() const override { return true; }
434+
435+
std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {
436+
return std::make_pair(32, 32);
437+
}
434438
};
435439
} // namespace targets
436440
} // namespace clang

clang/lib/Basic/Targets/PPC.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,10 @@ class LLVM_LIBRARY_VISIBILITY PPC32TargetInfo : public PPCTargetInfo {
423423
// This is the ELF definition
424424
return TargetInfo::PowerABIBuiltinVaList;
425425
}
426+
427+
std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {
428+
return std::make_pair(32, 32);
429+
}
426430
};
427431

428432
// Note: ABI differences may eventually require us to have a separate
@@ -503,6 +507,10 @@ class LLVM_LIBRARY_VISIBILITY PPC64TargetInfo : public PPCTargetInfo {
503507
return CCCR_Warning;
504508
}
505509
}
510+
511+
std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {
512+
return std::make_pair(128, 128);
513+
}
506514
};
507515

508516
class LLVM_LIBRARY_VISIBILITY AIXPPC32TargetInfo :

clang/lib/Basic/Targets/RISCV.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,10 @@ class RISCVTargetInfo : public TargetInfo {
122122
void fillValidTuneCPUList(SmallVectorImpl<StringRef> &Values) const override;
123123
bool supportsTargetAttributeTune() const override { return true; }
124124
ParsedTargetAttr parseTargetAttr(StringRef Str) const override;
125+
126+
std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {
127+
return std::make_pair(32, 32);
128+
}
125129
};
126130
class LLVM_LIBRARY_VISIBILITY RISCV32TargetInfo : public RISCVTargetInfo {
127131
public:

clang/lib/Basic/Targets/Sparc.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,10 @@ class LLVM_LIBRARY_VISIBILITY SparcTargetInfo : public TargetInfo {
140140
CPU = getCPUKind(Name);
141141
return CPU != CK_GENERIC;
142142
}
143+
144+
std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {
145+
return std::make_pair(32, 32);
146+
}
143147
};
144148

145149
// SPARC v8 is the 32-bit mode selected by Triple::sparc.

clang/lib/Basic/Targets/SystemZ.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,10 @@ class LLVM_LIBRARY_VISIBILITY SystemZTargetInfo : public TargetInfo {
220220
int getEHDataRegisterNumber(unsigned RegNo) const override {
221221
return RegNo < 4 ? 6 + RegNo : -1;
222222
}
223+
224+
std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {
225+
return std::make_pair(256, 256);
226+
}
223227
};
224228
} // namespace targets
225229
} // namespace clang

clang/lib/Frontend/InitPreprocessor.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1308,6 +1308,16 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
13081308
Builder.defineMacro("__GCC_ATOMIC_TEST_AND_SET_TRUEVAL", "1");
13091309
}
13101310

1311+
// GCC defines these macros in both C and C++ modes despite them being needed
1312+
// mostly for STL implementations in C++.
1313+
auto [Destructive, Constructive] = TI.hardwareInterferenceSizes();
1314+
Builder.defineMacro("__GCC_DESTRUCTIVE_SIZE", Twine(Destructive));
1315+
Builder.defineMacro("__GCC_CONSTRUCTIVE_SIZE", Twine(Constructive));
1316+
// We need to use push_macro to allow users to redefine these macros from the
1317+
// command line with -D and not issue a -Wmacro-redefined warning.
1318+
Builder.append("#pragma push_macro(\"__GCC_DESTRUCTIVE_SIZE\")");
1319+
Builder.append("#pragma push_macro(\"__GCC_CONSTRUCTIVE_SIZE\")");
1320+
13111321
auto addLockFreeMacros = [&](const llvm::Twine &Prefix) {
13121322
// Used by libc++ and libstdc++ to implement ATOMIC_<foo>_LOCK_FREE.
13131323
#define DEFINE_LOCK_FREE_MACRO(TYPE, Type) \

clang/test/AST/ast-dump-macro-json.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ void BLAP(foo, __COUNTER__)(void);
132132
// CHECK-NEXT: "spellingLoc": {
133133
// CHECK-NEXT: "offset": {{[0-9]+}},
134134
// CHECK-NEXT: "file": "<scratch space>",
135-
// CHECK-NEXT: "line": 3,
135+
// CHECK-NEXT: "line": 5,
136136
// CHECK-NEXT: "col": 1,
137137
// CHECK-NEXT: "tokLen": 4
138138
// CHECK-NEXT: },
@@ -169,7 +169,7 @@ void BLAP(foo, __COUNTER__)(void);
169169
// CHECK-NEXT: "spellingLoc": {
170170
// CHECK-NEXT: "offset": {{[0-9]+}},
171171
// CHECK-NEXT: "file": "<scratch space>",
172-
// CHECK-NEXT: "line": 5,
172+
// CHECK-NEXT: "line": 7,
173173
// CHECK-NEXT: "col": 1,
174174
// CHECK-NEXT: "tokLen": 4
175175
// CHECK-NEXT: },

clang/test/Analysis/html_diagnostics/relevant_lines/multifile.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@ int f(int coin) {
1111
// RUN: rm -rf %t.output
1212
// RUN: %clang_analyze_cc1 -analyze -analyzer-checker=core -analyzer-output html -o %t.output %s
1313
// RUN: cat %t.output/* | FileCheck %s --match-full-lines
14-
// CHECK: var relevant_lines = {"1": {"3": 1, "4": 1, "5": 1, "6": 1}, "3": {"3": 1, "4": 1, "5": 1, "6": 1, "7": 1}};
14+
// CHECK: var relevant_lines = {"1": {"3": 1, "4": 1, "5": 1, "6": 1}, "4": {"3": 1, "4": 1, "5": 1, "6": 1, "7": 1}};

clang/test/Lexer/update_consecutive_macro_address_space.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
// RUN: %clang -cc1 -print-stats %s 2>&1 | FileCheck %s
2-
// CHECK: 6 local SLocEntries allocated
2+
// CHECK: 7 local SLocEntries allocated
33
//
4-
// Verify that the macro arg expansion is split to two file ids, we have 6 file
5-
// ids rather than 5:
4+
// Verify that the macro arg expansion is split to two file ids, we have 7 file
5+
// ids rather than 6:
66
// 0: invalid file id
77
// 1: main file
88
// 2: builtin file
9-
// 3: macro expansion for X
10-
// 4: macro arg expansions for 1
11-
// 5: macro arg expansions for == 2
9+
// 3: scratch space for __GCC_[CON|DE]STRUCTIVE_SIZE macros
10+
// 4: macro expansion for X
11+
// 5: macro arg expansions for 1
12+
// 6: macro arg expansions for == 2
1213
#define X(x) (int)(x);
1314
void func() {
1415
X(1
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: %clang_cc1 -E -dM -D__GCC_CONSTRUCTIVE_SIZE=1000 -D__GCC_DESTRUCTIVE_SIZE=1001 %s -verify -Weverything | FileCheck %s
2+
// RUN: %clang_cc1 -D__GCC_CONSTRUCTIVE_SIZE=1000 -D__GCC_DESTRUCTIVE_SIZE=1001 %s -verify -Weverything
3+
// RUN: %clang_cc1 -E -dM -U__GCC_CONSTRUCTIVE_SIZE -U__GCC_DESTRUCTIVE_SIZE %s -verify -Weverything | FileCheck --check-prefix DISABLED %s
4+
// expected-no-diagnostics
5+
6+
// Validate that we can set a new value on the command line without issuing any
7+
// diagnostics and that we can disabled the macro on the command line without
8+
// issuing any diagnostics.
9+
10+
// CHECK: #define __GCC_CONSTRUCTIVE_SIZE 1000
11+
// CHECK: #define __GCC_DESTRUCTIVE_SIZE 1001
12+
// DISABLED-NOT: __GCC_CONSTRUCTIVE_SIZE
13+
// DISABLED-NOT: __GCC_DESTRUCTIVE_SIZE
14+
15+
int main() {
16+
return 0;
17+
}

clang/test/Preprocessor/init-aarch64.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@
119119
// AARCH64-NEXT: #define __FP_FAST_FMA 1
120120
// AARCH64-NEXT: #define __FP_FAST_FMAF 1
121121
// AARCH64-NEXT: #define __GCC_ASM_FLAG_OUTPUTS__ 1
122+
// AARCH64-NEXT: #define __GCC_CONSTRUCTIVE_SIZE {{.+}}
123+
// AARCH64-NEXT: #define __GCC_DESTRUCTIVE_SIZE {{.+}}
122124
// AARCH64-NEXT: #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
123125
// AARCH64-NEXT: #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16 1
124126
// AARCH64-NEXT: #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1
@@ -220,11 +222,11 @@
220222
// AARCH64-NEXT: #define __LONG_MAX__ 9223372036854775807L
221223
// AARCH64-NEXT: #define __LONG_WIDTH__ 64
222224
// AARCH64-NEXT: #define __LP64__ 1
223-
// AARCH64-NEXT: #define __MEMORY_SCOPE_DEVICE 1
224-
// AARCH64-NEXT: #define __MEMORY_SCOPE_SINGLE 4
225-
// AARCH64-NEXT: #define __MEMORY_SCOPE_SYSTEM 0
226-
// AARCH64-NEXT: #define __MEMORY_SCOPE_WRKGRP 2
227-
// AARCH64-NEXT: #define __MEMORY_SCOPE_WVFRNT 3
225+
// AARCH64-NEXT: #define __MEMORY_SCOPE_DEVICE 1
226+
// AARCH64-NEXT: #define __MEMORY_SCOPE_SINGLE 4
227+
// AARCH64-NEXT: #define __MEMORY_SCOPE_SYSTEM 0
228+
// AARCH64-NEXT: #define __MEMORY_SCOPE_WRKGRP 2
229+
// AARCH64-NEXT: #define __MEMORY_SCOPE_WVFRNT 3
228230
// AARCH64-NEXT: #define __NO_INLINE__ 1
229231
// AARCH64-NEXT: #define __NO_MATH_ERRNO__ 1
230232
// AARCH64-NEXT: #define __OBJC_BOOL_IS_BOOL 0

0 commit comments

Comments
 (0)