1*0b57cec5SDimitry Andric //===--- AMDGPUMachineModuleInfo.h ------------------------------*- C++ -*-===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric //
9*0b57cec5SDimitry Andric /// \file
10*0b57cec5SDimitry Andric /// AMDGPU Machine Module Info.
11*0b57cec5SDimitry Andric ///
12*0b57cec5SDimitry Andric //
13*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
14*0b57cec5SDimitry Andric 
15*0b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_AMDGPU_AMDGPUMACHINEMODULEINFO_H
16*0b57cec5SDimitry Andric #define LLVM_LIB_TARGET_AMDGPU_AMDGPUMACHINEMODULEINFO_H
17*0b57cec5SDimitry Andric 
18*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineModuleInfoImpls.h"
19*0b57cec5SDimitry Andric 
20*0b57cec5SDimitry Andric namespace llvm {
21*0b57cec5SDimitry Andric 
22*0b57cec5SDimitry Andric class AMDGPUMachineModuleInfo final : public MachineModuleInfoELF {
23*0b57cec5SDimitry Andric private:
24*0b57cec5SDimitry Andric 
25*0b57cec5SDimitry Andric   // All supported memory/synchronization scopes can be found here:
26*0b57cec5SDimitry Andric   //   http://llvm.org/docs/AMDGPUUsage.html#memory-scopes
27*0b57cec5SDimitry Andric 
28*0b57cec5SDimitry Andric   /// Agent synchronization scope ID (cross address space).
29*0b57cec5SDimitry Andric   SyncScope::ID AgentSSID;
30*0b57cec5SDimitry Andric   /// Workgroup synchronization scope ID (cross address space).
31*0b57cec5SDimitry Andric   SyncScope::ID WorkgroupSSID;
32*0b57cec5SDimitry Andric   /// Wavefront synchronization scope ID (cross address space).
33*0b57cec5SDimitry Andric   SyncScope::ID WavefrontSSID;
34*0b57cec5SDimitry Andric   /// System synchronization scope ID (single address space).
35*0b57cec5SDimitry Andric   SyncScope::ID SystemOneAddressSpaceSSID;
36*0b57cec5SDimitry Andric   /// Agent synchronization scope ID (single address space).
37*0b57cec5SDimitry Andric   SyncScope::ID AgentOneAddressSpaceSSID;
38*0b57cec5SDimitry Andric   /// Workgroup synchronization scope ID (single address space).
39*0b57cec5SDimitry Andric   SyncScope::ID WorkgroupOneAddressSpaceSSID;
40*0b57cec5SDimitry Andric   /// Wavefront synchronization scope ID (single address space).
41*0b57cec5SDimitry Andric   SyncScope::ID WavefrontOneAddressSpaceSSID;
42*0b57cec5SDimitry Andric   /// Single thread synchronization scope ID (single address space).
43*0b57cec5SDimitry Andric   SyncScope::ID SingleThreadOneAddressSpaceSSID;
44*0b57cec5SDimitry Andric 
45*0b57cec5SDimitry Andric   /// In AMDGPU target synchronization scopes are inclusive, meaning a
46*0b57cec5SDimitry Andric   /// larger synchronization scope is inclusive of a smaller synchronization
47*0b57cec5SDimitry Andric   /// scope.
48*0b57cec5SDimitry Andric   ///
49*0b57cec5SDimitry Andric   /// \returns \p SSID's inclusion ordering, or "std::nullopt" if \p SSID is not
50*0b57cec5SDimitry Andric   /// supported by the AMDGPU target.
51*0b57cec5SDimitry Andric   std::optional<uint8_t>
getSyncScopeInclusionOrdering(SyncScope::ID SSID)52*0b57cec5SDimitry Andric   getSyncScopeInclusionOrdering(SyncScope::ID SSID) const {
53*0b57cec5SDimitry Andric     if (SSID == SyncScope::SingleThread ||
54*0b57cec5SDimitry Andric         SSID == getSingleThreadOneAddressSpaceSSID())
55*0b57cec5SDimitry Andric       return 0;
56*0b57cec5SDimitry Andric     else if (SSID == getWavefrontSSID() ||
57*0b57cec5SDimitry Andric              SSID == getWavefrontOneAddressSpaceSSID())
58*0b57cec5SDimitry Andric       return 1;
59*0b57cec5SDimitry Andric     else if (SSID == getWorkgroupSSID() ||
60*0b57cec5SDimitry Andric              SSID == getWorkgroupOneAddressSpaceSSID())
61*0b57cec5SDimitry Andric       return 2;
62*0b57cec5SDimitry Andric     else if (SSID == getAgentSSID() ||
63*0b57cec5SDimitry Andric              SSID == getAgentOneAddressSpaceSSID())
64*0b57cec5SDimitry Andric       return 3;
65*0b57cec5SDimitry Andric     else if (SSID == SyncScope::System ||
66*0b57cec5SDimitry Andric              SSID == getSystemOneAddressSpaceSSID())
67*0b57cec5SDimitry Andric       return 4;
68*0b57cec5SDimitry Andric 
69*0b57cec5SDimitry Andric     return std::nullopt;
70*0b57cec5SDimitry Andric   }
71*0b57cec5SDimitry Andric 
72*0b57cec5SDimitry Andric   /// \returns True if \p SSID is restricted to single address space, false
73*0b57cec5SDimitry Andric   /// otherwise
isOneAddressSpace(SyncScope::ID SSID)74*0b57cec5SDimitry Andric   bool isOneAddressSpace(SyncScope::ID SSID) const {
75*0b57cec5SDimitry Andric     return SSID == getSingleThreadOneAddressSpaceSSID() ||
76*0b57cec5SDimitry Andric         SSID == getWavefrontOneAddressSpaceSSID() ||
77*0b57cec5SDimitry Andric         SSID == getWorkgroupOneAddressSpaceSSID() ||
78*0b57cec5SDimitry Andric         SSID == getAgentOneAddressSpaceSSID() ||
79*0b57cec5SDimitry Andric         SSID == getSystemOneAddressSpaceSSID();
80*0b57cec5SDimitry Andric   }
81*0b57cec5SDimitry Andric 
82*0b57cec5SDimitry Andric public:
83*0b57cec5SDimitry Andric   AMDGPUMachineModuleInfo(const MachineModuleInfo &MMI);
84*0b57cec5SDimitry Andric 
85*0b57cec5SDimitry Andric   /// \returns Agent synchronization scope ID (cross address space).
getAgentSSID()86*0b57cec5SDimitry Andric   SyncScope::ID getAgentSSID() const {
87*0b57cec5SDimitry Andric     return AgentSSID;
88*0b57cec5SDimitry Andric   }
89*0b57cec5SDimitry Andric   /// \returns Workgroup synchronization scope ID (cross address space).
getWorkgroupSSID()90*0b57cec5SDimitry Andric   SyncScope::ID getWorkgroupSSID() const {
91*0b57cec5SDimitry Andric     return WorkgroupSSID;
92*0b57cec5SDimitry Andric   }
93*0b57cec5SDimitry Andric   /// \returns Wavefront synchronization scope ID (cross address space).
getWavefrontSSID()94*0b57cec5SDimitry Andric   SyncScope::ID getWavefrontSSID() const {
95*0b57cec5SDimitry Andric     return WavefrontSSID;
96*0b57cec5SDimitry Andric   }
97*0b57cec5SDimitry Andric   /// \returns System synchronization scope ID (single address space).
getSystemOneAddressSpaceSSID()98*0b57cec5SDimitry Andric   SyncScope::ID getSystemOneAddressSpaceSSID() const {
99*0b57cec5SDimitry Andric     return SystemOneAddressSpaceSSID;
100*0b57cec5SDimitry Andric   }
101*0b57cec5SDimitry Andric   /// \returns Agent synchronization scope ID (single address space).
getAgentOneAddressSpaceSSID()102*0b57cec5SDimitry Andric   SyncScope::ID getAgentOneAddressSpaceSSID() const {
103*0b57cec5SDimitry Andric     return AgentOneAddressSpaceSSID;
104*0b57cec5SDimitry Andric   }
105*0b57cec5SDimitry Andric   /// \returns Workgroup synchronization scope ID (single address space).
getWorkgroupOneAddressSpaceSSID()106*0b57cec5SDimitry Andric   SyncScope::ID getWorkgroupOneAddressSpaceSSID() const {
107*0b57cec5SDimitry Andric     return WorkgroupOneAddressSpaceSSID;
108*0b57cec5SDimitry Andric   }
109*0b57cec5SDimitry Andric   /// \returns Wavefront synchronization scope ID (single address space).
getWavefrontOneAddressSpaceSSID()110*0b57cec5SDimitry Andric   SyncScope::ID getWavefrontOneAddressSpaceSSID() const {
111*0b57cec5SDimitry Andric     return WavefrontOneAddressSpaceSSID;
112*0b57cec5SDimitry Andric   }
113*0b57cec5SDimitry Andric   /// \returns Single thread synchronization scope ID (single address space).
getSingleThreadOneAddressSpaceSSID()114*0b57cec5SDimitry Andric   SyncScope::ID getSingleThreadOneAddressSpaceSSID() const {
115*0b57cec5SDimitry Andric     return SingleThreadOneAddressSpaceSSID;
116*0b57cec5SDimitry Andric   }
117*0b57cec5SDimitry Andric 
118*0b57cec5SDimitry Andric   /// In AMDGPU target synchronization scopes are inclusive, meaning a
119*0b57cec5SDimitry Andric   /// larger synchronization scope is inclusive of a smaller synchronization
120*0b57cec5SDimitry Andric   /// scope.
121*0b57cec5SDimitry Andric   ///
122*0b57cec5SDimitry Andric   /// \returns True if synchronization scope \p A is larger than or equal to
123*0b57cec5SDimitry Andric   /// synchronization scope \p B, false if synchronization scope \p A is smaller
124*0b57cec5SDimitry Andric   /// than synchronization scope \p B, or "std::nullopt" if either
125*0b57cec5SDimitry Andric   /// synchronization scope \p A or \p B is not supported by the AMDGPU target.
isSyncScopeInclusion(SyncScope::ID A,SyncScope::ID B)126*0b57cec5SDimitry Andric   std::optional<bool> isSyncScopeInclusion(SyncScope::ID A,
127*0b57cec5SDimitry Andric                                            SyncScope::ID B) const {
128*0b57cec5SDimitry Andric     const auto &AIO = getSyncScopeInclusionOrdering(A);
129*0b57cec5SDimitry Andric     const auto &BIO = getSyncScopeInclusionOrdering(B);
130*0b57cec5SDimitry Andric     if (!AIO || !BIO)
131*0b57cec5SDimitry Andric       return std::nullopt;
132*0b57cec5SDimitry Andric 
133*0b57cec5SDimitry Andric     bool IsAOneAddressSpace = isOneAddressSpace(A);
134*0b57cec5SDimitry Andric     bool IsBOneAddressSpace = isOneAddressSpace(B);
135*0b57cec5SDimitry Andric 
136*0b57cec5SDimitry Andric     return *AIO >= *BIO &&
137*0b57cec5SDimitry Andric            (IsAOneAddressSpace == IsBOneAddressSpace || !IsAOneAddressSpace);
138*0b57cec5SDimitry Andric   }
139*0b57cec5SDimitry Andric };
140*0b57cec5SDimitry Andric 
141*0b57cec5SDimitry Andric } // end namespace llvm
142*0b57cec5SDimitry Andric 
143*0b57cec5SDimitry Andric #endif // LLVM_LIB_TARGET_AMDGPU_AMDGPUMACHINEMODULEINFO_H
144*0b57cec5SDimitry Andric