1//===--- AMDGPUMachineModuleInfo.h ------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9/// \file
10/// AMDGPU Machine Module Info.
11///
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_LIB_TARGET_AMDGPU_AMDGPUMACHINEMODULEINFO_H
16#define LLVM_LIB_TARGET_AMDGPU_AMDGPUMACHINEMODULEINFO_H
17
18#include "llvm/CodeGen/MachineModuleInfoImpls.h"
19#include "llvm/IR/LLVMContext.h"
20
21namespace llvm {
22
23class AMDGPUMachineModuleInfo final : public MachineModuleInfoELF {
24private:
25
26 // All supported memory/synchronization scopes can be found here:
27 // http://llvm.org/docs/AMDGPUUsage.html#memory-scopes
28
29 /// Agent synchronization scope ID (cross address space).
30 SyncScope::ID AgentSSID;
31 /// Workgroup synchronization scope ID (cross address space).
32 SyncScope::ID WorkgroupSSID;
33 /// Wavefront synchronization scope ID (cross address space).
34 SyncScope::ID WavefrontSSID;
35 /// Cluster synchronization scope ID (cross address space).
36 SyncScope::ID ClusterSSID;
37 /// System synchronization scope ID (single address space).
38 SyncScope::ID SystemOneAddressSpaceSSID;
39 /// Agent synchronization scope ID (single address space).
40 SyncScope::ID AgentOneAddressSpaceSSID;
41 /// Workgroup synchronization scope ID (single address space).
42 SyncScope::ID WorkgroupOneAddressSpaceSSID;
43 /// Wavefront synchronization scope ID (single address space).
44 SyncScope::ID WavefrontOneAddressSpaceSSID;
45 /// Single thread synchronization scope ID (single address space).
46 SyncScope::ID SingleThreadOneAddressSpaceSSID;
47 /// Cluster synchronization scope ID (single address space).
48 SyncScope::ID ClusterOneAddressSpaceSSID;
49
50public:
51 AMDGPUMachineModuleInfo(const MachineModuleInfo &MMI);
52
53 /// \returns Agent synchronization scope ID (cross address space).
54 SyncScope::ID getAgentSSID() const {
55 return AgentSSID;
56 }
57 /// \returns Workgroup synchronization scope ID (cross address space).
58 SyncScope::ID getWorkgroupSSID() const {
59 return WorkgroupSSID;
60 }
61 /// \returns Wavefront synchronization scope ID (cross address space).
62 SyncScope::ID getWavefrontSSID() const {
63 return WavefrontSSID;
64 }
65 /// \returns Cluster synchronization scope ID (cross address space).
66 SyncScope::ID getClusterSSID() const { return ClusterSSID; }
67 /// \returns System synchronization scope ID (single address space).
68 SyncScope::ID getSystemOneAddressSpaceSSID() const {
69 return SystemOneAddressSpaceSSID;
70 }
71 /// \returns Agent synchronization scope ID (single address space).
72 SyncScope::ID getAgentOneAddressSpaceSSID() const {
73 return AgentOneAddressSpaceSSID;
74 }
75 /// \returns Workgroup synchronization scope ID (single address space).
76 SyncScope::ID getWorkgroupOneAddressSpaceSSID() const {
77 return WorkgroupOneAddressSpaceSSID;
78 }
79 /// \returns Wavefront synchronization scope ID (single address space).
80 SyncScope::ID getWavefrontOneAddressSpaceSSID() const {
81 return WavefrontOneAddressSpaceSSID;
82 }
83 /// \returns Single thread synchronization scope ID (single address space).
84 SyncScope::ID getSingleThreadOneAddressSpaceSSID() const {
85 return SingleThreadOneAddressSpaceSSID;
86 }
87 /// \returns Single thread synchronization scope ID (single address space).
88 SyncScope::ID getClusterOneAddressSpaceSSID() const {
89 return ClusterOneAddressSpaceSSID;
90 }
91
92 /// In AMDGPU, synchronization scopes are inclusive: a larger scope is
93 /// inclusive of a smaller one (e.g. agent includes workgroup).
94 ///
95 /// Returns the merged synchronization scope of \p A and \p B: the smallest
96 /// scope that is inclusive of both. Takes the larger inclusion level and,
97 /// if either scope is cross-address-space, the result is also
98 /// cross-address-space (since a one-AS scope cannot subsume a cross-AS
99 /// scope at the same level).
100 ///
101 /// \returns The merged scope ID, or "std::nullopt" if either scope is not
102 /// supported by the AMDGPU target.
103 std::optional<SyncScope::ID> getMergedSyncScopeID(SyncScope::ID A,
104 SyncScope::ID B) const {
105 // Ordered from smallest to largest scope. Level is the index.
106 // Cross-AS and one-AS scopes share the same inclusion ordering level.
107 // Level | Cross-AS scope | One-AS scope
108 // ------+------------------+----------------------
109 // 0 | singlethread | singlethread-one-as
110 // 1 | wavefront | wavefront-one-as
111 // 2 | workgroup | workgroup-one-as
112 // 3 | cluster | cluster-one-as
113 // 4 | agent | agent-one-as
114 // 5 | system | one-as
115 const SyncScope::ID CrossAS[] = {
116 SyncScope::SingleThread, getWavefrontSSID(), getWorkgroupSSID(),
117 getClusterSSID(), getAgentSSID(), SyncScope::System};
118 const SyncScope::ID OneAS[] = {
119 getSingleThreadOneAddressSpaceSSID(), getWavefrontOneAddressSpaceSSID(),
120 getWorkgroupOneAddressSpaceSSID(), getClusterOneAddressSpaceSSID(),
121 getAgentOneAddressSpaceSSID(), getSystemOneAddressSpaceSSID()};
122
123 // Returns {level, isOneAS} for a given scope, or nullopt if unsupported.
124 auto GetLevelAndOneAS =
125 [&](SyncScope::ID SSID) -> std::optional<std::pair<unsigned, bool>> {
126 for (auto [I, Cross, One] : llvm::enumerate(First: CrossAS, Rest: OneAS)) {
127 if (Cross == SSID)
128 return std::make_pair(x&: I, y: false);
129 if (One == SSID)
130 return std::make_pair(x&: I, y: true);
131 }
132 return std::nullopt;
133 };
134
135 auto AI = GetLevelAndOneAS(A);
136 auto BI = GetLevelAndOneAS(B);
137 if (!AI || !BI)
138 return std::nullopt;
139
140 unsigned Level = std::max(a: AI->first, b: BI->first);
141 // If either scope is cross-AS, the result must be cross-AS.
142 return (AI->second && BI->second) ? OneAS[Level] : CrossAS[Level];
143 }
144};
145
146} // end namespace llvm
147
148#endif // LLVM_LIB_TARGET_AMDGPU_AMDGPUMACHINEMODULEINFO_H
149