Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[C++17] Support __GCC_[CON|DE]STRUCTIVE_SIZE #89446

Merged
merged 14 commits into from
Apr 26, 2024
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions clang-tools-extra/test/pp-trace/pp-trace-pragma-general.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ void foo() {

// CHECK: ---
// CHECK-NEXT: - Callback: PragmaDirective
// CHECK-NEXT: Loc: "<built-in>:{{.+}}:1"
// CHECK-NEXT: Introducer: PIK_HashPragma
// CHECK-NEXT: - Callback: PragmaDirective
// CHECK-NEXT: Loc: "<built-in>:{{.+}}:1"
// CHECK-NEXT: Introducer: PIK_HashPragma
// CHECK-NEXT: - Callback: PragmaDirective
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-general.cpp:3:1"
// CHECK-NEXT: Introducer: PIK_HashPragma
// CHECK-NEXT: - Callback: PragmaDiagnosticPush
Expand Down
8 changes: 7 additions & 1 deletion clang-tools-extra/test/pp-trace/pp-trace-pragma-ms.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@

// CHECK: ---
// CHECK-NEXT: - Callback: PragmaDirective
// CHECK-NEXT: Loc: "<built-in>:{{.+}}:1"
// CHECK-NEXT: Introducer: PIK_HashPragma
// CHECK-NEXT: - Callback: PragmaDirective
// CHECK-NEXT: Loc: "<built-in>:{{.+}}:1"
// CHECK-NEXT: Introducer: PIK_HashPragma
// CHECK-NEXT: - Callback: PragmaDirective
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-ms.cpp:3:1"
// CHECK-NEXT: Introducer: PIK_HashPragma
// CHECK-NEXT: - Callback: PragmaComment
Expand Down Expand Up @@ -67,7 +73,7 @@
// CHECK-NEXT: Introducer: PIK_HashPragma
// CHECK-NEXT: - Callback: PragmaMessage
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-ms.cpp:13:9"
// CHECK-NEXT: Namespace:
// CHECK-NEXT: Namespace:
// CHECK-NEXT: Kind: PMK_Message
// CHECK-NEXT: Str: message argument
// CHECK-NEXT: - Callback: PragmaDirective
Expand Down
6 changes: 6 additions & 0 deletions clang-tools-extra/test/pp-trace/pp-trace-pragma-opencl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@

// CHECK: ---
// CHECK-NEXT: - Callback: PragmaDirective
// CHECK-NEXT: Loc: "<built-in>:{{.+}}:1"
// CHECK-NEXT: Introducer: PIK_HashPragma
// CHECK-NEXT: - Callback: PragmaDirective
// CHECK-NEXT: Loc: "<built-in>:{{.+}}:1"
// CHECK-NEXT: Introducer: PIK_HashPragma
// CHECK-NEXT: - Callback: PragmaDirective
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-opencl.cpp:3:1"
// CHECK-NEXT: Introducer: PIK_HashPragma
// CHECK-NEXT: - Callback: PragmaOpenCLExtension
Expand Down
16 changes: 16 additions & 0 deletions clang/docs/LanguageExtensions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5571,3 +5571,19 @@ but the expression has no runtime effects.
Type- and value-dependent expressions are not supported yet.

This facility is designed to aid with testing name lookup machinery.

Predefined Macros
=================

`__GCC_DESTRUCTIVE_SIZE` and `__GCC_CONSTRUCTIVE_SIZE`
------------------------------------------------------
Specify the mimum offset between two objects to avoid false sharing and the
maximum size of contiguous memory to promote true sharing, respectively. These
macros are predefined in all C and C++ language modes, but can be redefined on
the command line with ``-D`` to specify different values as needed or can be
undefined on the command line with ``-U`` to disable support for the feature.

**Note: the values the macros expand to are not stable between releases of Clang
and do not need to match the values produced by GCC, so these macros should not
be used from header files because they may not be stable across multiple TUs
(the values may vary based on compiler version as well as CPU tuning).**
Copy link
Contributor

@cor3ntin cor3ntin Apr 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
**Note: the values the macros expand to are not stable between releases of Clang
and do not need to match the values produced by GCC, so these macros should not
be used from header files because they may not be stable across multiple TUs
(the values may vary based on compiler version as well as CPU tuning).**
**Note: the values the macros expand to are not guaranteed to be stable. They are are affected by architectures and CPU tuning flags, can change between releases of Clang and will not match the values defined by other compilers such as GCC.**
**Compiling different TUs depending on these flags (or `std::hardware_constructive_interference` , `std::hardware_destructive_interference`) with different compilers, defines or architecture flags will lead to ODR violations bugs and should be avoided.**

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

12 changes: 12 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,18 @@ sections with improvements to Clang's support for those languages.
C++ Language Changes
--------------------

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

C++20 Feature Support
^^^^^^^^^^^^^^^^^^^^^

Expand Down
10 changes: 10 additions & 0 deletions clang/include/clang/Basic/TargetInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include <cassert>
#include <optional>
#include <string>
#include <utility>
#include <vector>

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

/// The first value in the pair is the minimum offset between two objects to
/// avoid false sharing (destructive interference). The second value in the
/// pair is maximum size of contiguous memory to promote true sharing
/// (constructive interference). Neither of these values are considered part
/// of the ABI and can be changed by targets at any time.
virtual std::pair<unsigned, unsigned> hardwareInterferenceSizes() const {
return std::make_pair(64, 64);
}

protected:
/// Copy type and layout related info.
void copyAuxTarget(const TargetInfo *Aux);
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Basic/Targets/ARM.h
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,10 @@ class LLVM_LIBRARY_VISIBILITY ARMTargetInfo : public TargetInfo {
bool hasBitIntType() const override { return true; }

const char *getBFloat16Mangling() const override { return "u6__bf16"; };

std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {
return std::make_pair(getTriple().isArch64Bit() ? 256 : 64, 64);
}
};

class LLVM_LIBRARY_VISIBILITY ARMleTargetInfo : public ARMTargetInfo {
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Basic/Targets/AVR.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,10 @@ class LLVM_LIBRARY_VISIBILITY AVRTargetInfo : public TargetInfo {
std::optional<std::string> handleAsmEscapedChar(char EscChar) const override;
StringRef getABI() const override { return ABI; }

std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {
return std::make_pair(32, 32);
}

protected:
std::string CPU;
StringRef ABI;
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Basic/Targets/BPF.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ class LLVM_LIBRARY_VISIBILITY BPFTargetInfo : public TargetInfo {
StringRef CPUName(Name);
return isValidCPUName(CPUName);
}

std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {
return std::make_pair(32, 32);
}
};
} // namespace targets
} // namespace clang
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Basic/Targets/M68k.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ class LLVM_LIBRARY_VISIBILITY M68kTargetInfo : public TargetInfo {
BuiltinVaListKind getBuiltinVaListKind() const override;
bool setCPU(const std::string &Name) override;
CallingConvCheckResult checkCallingConvention(CallingConv CC) const override;

std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {
return std::make_pair(32, 32);
}
};

} // namespace targets
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Basic/Targets/Mips.h
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,10 @@ class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo {

bool validateTarget(DiagnosticsEngine &Diags) const override;
bool hasBitIntType() const override { return true; }

std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {
return std::make_pair(32, 32);
}
};
} // namespace targets
} // namespace clang
Expand Down
8 changes: 8 additions & 0 deletions clang/lib/Basic/Targets/PPC.h
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,10 @@ class LLVM_LIBRARY_VISIBILITY PPC32TargetInfo : public PPCTargetInfo {
// This is the ELF definition
return TargetInfo::PowerABIBuiltinVaList;
}

std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {
return std::make_pair(32, 32);
}
};

// Note: ABI differences may eventually require us to have a separate
Expand Down Expand Up @@ -502,6 +506,10 @@ class LLVM_LIBRARY_VISIBILITY PPC64TargetInfo : public PPCTargetInfo {
return CCCR_Warning;
}
}

std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {
return std::make_pair(128, 128);
}
};

class LLVM_LIBRARY_VISIBILITY AIXPPC32TargetInfo :
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Basic/Targets/RISCV.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,10 @@ class RISCVTargetInfo : public TargetInfo {
void fillValidTuneCPUList(SmallVectorImpl<StringRef> &Values) const override;
bool supportsTargetAttributeTune() const override { return true; }
ParsedTargetAttr parseTargetAttr(StringRef Str) const override;

std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {
return std::make_pair(32, 32);
}
};
class LLVM_LIBRARY_VISIBILITY RISCV32TargetInfo : public RISCVTargetInfo {
public:
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Basic/Targets/Sparc.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,10 @@ class LLVM_LIBRARY_VISIBILITY SparcTargetInfo : public TargetInfo {
CPU = getCPUKind(Name);
return CPU != CK_GENERIC;
}

std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {
return std::make_pair(32, 32);
}
};

// SPARC v8 is the 32-bit mode selected by Triple::sparc.
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Basic/Targets/SystemZ.h
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,10 @@ class LLVM_LIBRARY_VISIBILITY SystemZTargetInfo : public TargetInfo {
int getEHDataRegisterNumber(unsigned RegNo) const override {
return RegNo < 4 ? 6 + RegNo : -1;
}

std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {
return std::make_pair(256, 256);
}
};
} // namespace targets
} // namespace clang
Expand Down
10 changes: 10 additions & 0 deletions clang/lib/Frontend/InitPreprocessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1309,6 +1309,16 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
Builder.defineMacro("__GCC_ATOMIC_TEST_AND_SET_TRUEVAL", "1");
}

// GCC defines these macros in both C and C++ modes despite them being needed
// mostly for STL implementations in C++.
auto [Destructive, Constructive] = TI.hardwareInterferenceSizes();
Builder.defineMacro("__GCC_DESTRUCTIVE_SIZE", Twine(Destructive));
Builder.defineMacro("__GCC_CONSTRUCTIVE_SIZE", Twine(Constructive));
// We need to use push_macro to allow users to redefine these macros from the
// command line with -D and not issue a -Wmacro-redefined warning.
Builder.append("#pragma push_macro(\"__GCC_DESTRUCTIVE_SIZE\")");
Builder.append("#pragma push_macro(\"__GCC_CONSTRUCTIVE_SIZE\")");

auto addLockFreeMacros = [&](const llvm::Twine &Prefix) {
// Used by libc++ and libstdc++ to implement ATOMIC_<foo>_LOCK_FREE.
#define DEFINE_LOCK_FREE_MACRO(TYPE, Type) \
Expand Down
4 changes: 2 additions & 2 deletions clang/test/AST/ast-dump-macro-json.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ void BLAP(foo, __COUNTER__)(void);
// CHECK-NEXT: "spellingLoc": {
// CHECK-NEXT: "offset": {{[0-9]+}},
// CHECK-NEXT: "file": "<scratch space>",
// CHECK-NEXT: "line": 3,
// CHECK-NEXT: "line": 5,
// CHECK-NEXT: "col": 1,
// CHECK-NEXT: "tokLen": 4
// CHECK-NEXT: },
Expand Down Expand Up @@ -169,7 +169,7 @@ void BLAP(foo, __COUNTER__)(void);
// CHECK-NEXT: "spellingLoc": {
// CHECK-NEXT: "offset": {{[0-9]+}},
// CHECK-NEXT: "file": "<scratch space>",
// CHECK-NEXT: "line": 5,
// CHECK-NEXT: "line": 7,
// CHECK-NEXT: "col": 1,
// CHECK-NEXT: "tokLen": 4
// CHECK-NEXT: },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ int f(int coin) {
// RUN: rm -rf %t.output
// RUN: %clang_analyze_cc1 -analyze -analyzer-checker=core -analyzer-output html -o %t.output %s
// RUN: cat %t.output/* | FileCheck %s --match-full-lines
// CHECK: var relevant_lines = {"1": {"3": 1, "4": 1, "5": 1, "6": 1}, "3": {"3": 1, "4": 1, "5": 1, "6": 1, "7": 1}};
// CHECK: var relevant_lines = {"1": {"3": 1, "4": 1, "5": 1, "6": 1}, "4": {"3": 1, "4": 1, "5": 1, "6": 1, "7": 1}};
13 changes: 7 additions & 6 deletions clang/test/Lexer/update_consecutive_macro_address_space.c
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
// RUN: %clang -cc1 -print-stats %s 2>&1 | FileCheck %s
// CHECK: 6 local SLocEntries allocated
// CHECK: 7 local SLocEntries allocated
//
// Verify that the macro arg expansion is split to two file ids, we have 6 file
// ids rather than 5:
// Verify that the macro arg expansion is split to two file ids, we have 7 file
// ids rather than 6:
// 0: invalid file id
// 1: main file
// 2: builtin file
// 3: macro expansion for X
// 4: macro arg expansions for 1
// 5: macro arg expansions for == 2
// 3: scratch space for __GCC_[CON|DE]STRUCTIVE_SIZE macros
// 4: macro expansion for X
// 5: macro arg expansions for 1
// 6: macro arg expansions for == 2
#define X(x) (int)(x);
void func() {
X(1
Expand Down
17 changes: 17 additions & 0 deletions clang/test/Preprocessor/hardware_interference.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// RUN: %clang_cc1 -E -dM -D__GCC_CONSTRUCTIVE_SIZE=1000 -D__GCC_DESTRUCTIVE_SIZE=1001 %s -verify -Weverything | FileCheck %s
// RUN: %clang_cc1 -D__GCC_CONSTRUCTIVE_SIZE=1000 -D__GCC_DESTRUCTIVE_SIZE=1001 %s -verify -Weverything
// RUN: %clang_cc1 -E -dM -U__GCC_CONSTRUCTIVE_SIZE -U__GCC_DESTRUCTIVE_SIZE %s -verify -Weverything | FileCheck --check-prefix DISABLED %s
// expected-no-diagnostics

// Validate that we can set a new value on the command line without issuing any
// diagnostics and that we can disabled the macro on the command line without
// issuing any diagnostics.

// CHECK: #define __GCC_CONSTRUCTIVE_SIZE 1000
// CHECK: #define __GCC_DESTRUCTIVE_SIZE 1001
// DISABLED-NOT: __GCC_CONSTRUCTIVE_SIZE
// DISABLED-NOT: __GCC_DESTRUCTIVE_SIZE

int main() {
return 0;
}
12 changes: 7 additions & 5 deletions clang/test/Preprocessor/init-aarch64.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@
// AARCH64-NEXT: #define __FP_FAST_FMA 1
// AARCH64-NEXT: #define __FP_FAST_FMAF 1
// AARCH64-NEXT: #define __GCC_ASM_FLAG_OUTPUTS__ 1
// AARCH64-NEXT: #define __GCC_CONSTRUCTIVE_SIZE {{.+}}
// AARCH64-NEXT: #define __GCC_DESTRUCTIVE_SIZE {{.+}}
// AARCH64-NEXT: #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
// AARCH64-NEXT: #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16 1
// AARCH64-NEXT: #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1
Expand Down Expand Up @@ -220,11 +222,11 @@
// AARCH64-NEXT: #define __LONG_MAX__ 9223372036854775807L
// AARCH64-NEXT: #define __LONG_WIDTH__ 64
// AARCH64-NEXT: #define __LP64__ 1
// AARCH64-NEXT: #define __MEMORY_SCOPE_DEVICE 1
// AARCH64-NEXT: #define __MEMORY_SCOPE_SINGLE 4
// AARCH64-NEXT: #define __MEMORY_SCOPE_SYSTEM 0
// AARCH64-NEXT: #define __MEMORY_SCOPE_WRKGRP 2
// AARCH64-NEXT: #define __MEMORY_SCOPE_WVFRNT 3
// AARCH64-NEXT: #define __MEMORY_SCOPE_DEVICE 1
// AARCH64-NEXT: #define __MEMORY_SCOPE_SINGLE 4
// AARCH64-NEXT: #define __MEMORY_SCOPE_SYSTEM 0
// AARCH64-NEXT: #define __MEMORY_SCOPE_WRKGRP 2
// AARCH64-NEXT: #define __MEMORY_SCOPE_WVFRNT 3
// AARCH64-NEXT: #define __NO_INLINE__ 1
// AARCH64-NEXT: #define __NO_MATH_ERRNO__ 1
// AARCH64-NEXT: #define __OBJC_BOOL_IS_BOOL 0
Expand Down
Loading
Loading