19#include "llvm/IR/IntrinsicsAMDGPU.h"
23#define DEBUG_TYPE "amdgpu-lower-intrinsics"
29class AMDGPULowerIntrinsicsImpl {
45class AMDGPULowerIntrinsicsLegacy :
public ModulePass {
49 AMDGPULowerIntrinsicsLegacy() :
ModulePass(ID) {}
51 bool runOnModule(
Module &M)
override;
67bool AMDGPULowerIntrinsicsImpl::run() {
71 switch (
F.getIntrinsicID()) {
74 case Intrinsic::amdgcn_s_barrier:
75 case Intrinsic::amdgcn_s_barrier_signal:
76 case Intrinsic::amdgcn_s_barrier_signal_isfirst:
77 case Intrinsic::amdgcn_s_barrier_wait:
78 case Intrinsic::amdgcn_s_cluster_barrier:
81 case Intrinsic::amdgcn_ptr_s_buffer_load:
83 F, [&](IntrinsicInst *
II) {
Changed |= visitPtrSBufferLoad(*
II); });
85 case Intrinsic::amdgcn_s_monitor_sleep:
87 F, [&](IntrinsicInst *
II) {
Changed |= visitMonitorSleep(*
II); });
97bool AMDGPULowerIntrinsicsImpl::visitBarrier(IntrinsicInst &
I) {
98 assert(
I.getIntrinsicID() == Intrinsic::amdgcn_s_barrier ||
99 I.getIntrinsicID() == Intrinsic::amdgcn_s_barrier_signal ||
100 I.getIntrinsicID() == Intrinsic::amdgcn_s_barrier_signal_isfirst ||
101 I.getIntrinsicID() == Intrinsic::amdgcn_s_barrier_wait ||
102 I.getIntrinsicID() == Intrinsic::amdgcn_s_cluster_barrier);
104 const GCNSubtarget &
ST = TM.
getSubtarget<GCNSubtarget>(*
I.getFunction());
105 bool IsSingleWaveWG =
false;
108 unsigned WGMaxSize =
ST.getFlatWorkGroupSizes(*
I.getFunction()).second;
109 IsSingleWaveWG = WGMaxSize <=
ST.getWavefrontSize();
116 if (
I.getIntrinsicID() == Intrinsic::amdgcn_s_cluster_barrier) {
119 if (IsSingleWaveWG) {
120 B.CreateIntrinsicWithoutFolding(
B.getVoidTy(),
121 Intrinsic::amdgcn_wave_barrier, {})
126 CallInst *IsFirst =
B.CreateIntrinsicWithoutFolding(
127 B.getInt1Ty(), Intrinsic::amdgcn_s_barrier_signal_isfirst,
130 B.CreateIntrinsicWithoutFolding(
131 B.getVoidTy(), Intrinsic::amdgcn_s_barrier_wait, {BarrierID_16})
136 B.SetInsertPoint(ThenTerm);
143 B.CreateIntrinsicWithoutFolding(
144 B.getVoidTy(), Intrinsic::amdgcn_s_barrier_signal, {BarrierID_32})
147 B.SetInsertPoint(&
I);
148 B.CreateIntrinsicWithoutFolding(
149 B.getVoidTy(), Intrinsic::amdgcn_s_barrier_wait, {BarrierID_16})
156 bool IsWorkgroupScope =
false;
158 if (
I.getIntrinsicID() == Intrinsic::amdgcn_s_barrier_wait ||
159 I.getIntrinsicID() == Intrinsic::amdgcn_s_barrier_signal ||
160 I.getIntrinsicID() == Intrinsic::amdgcn_s_barrier_signal_isfirst) {
166 IsWorkgroupScope =
true;
168 assert(
I.getIntrinsicID() == Intrinsic::amdgcn_s_barrier);
169 IsWorkgroupScope =
true;
172 if (IsWorkgroupScope && IsSingleWaveWG) {
174 if (
I.getIntrinsicID() == Intrinsic::amdgcn_s_barrier ||
175 I.getIntrinsicID() == Intrinsic::amdgcn_s_barrier_wait) {
176 B.CreateIntrinsicWithoutFolding(
B.getVoidTy(),
177 Intrinsic::amdgcn_wave_barrier, {})
179 }
else if (
I.getIntrinsicID() ==
180 Intrinsic::amdgcn_s_barrier_signal_isfirst) {
182 I.replaceAllUsesWith(
B.getInt1(
true));
188 if (
I.getIntrinsicID() == Intrinsic::amdgcn_s_barrier &&
189 ST.hasSplitBarriers()) {
193 B.CreateIntrinsicWithoutFolding(
194 B.getVoidTy(), Intrinsic::amdgcn_s_barrier_signal, {BarrierID_32})
196 B.CreateIntrinsicWithoutFolding(
197 B.getVoidTy(), Intrinsic::amdgcn_s_barrier_wait, {BarrierID_16})
206bool AMDGPULowerIntrinsicsImpl::visitPtrSBufferLoad(IntrinsicInst &
I) {
207 assert(
I.getIntrinsicID() == Intrinsic::amdgcn_ptr_s_buffer_load);
209 if (
I.hasMetadata(LLVMContext::MD_invariant_load))
212 I.setMetadata(LLVMContext::MD_invariant_load,
217bool AMDGPULowerIntrinsicsImpl::visitMonitorSleep(IntrinsicInst &
I) {
218 assert(
I.getIntrinsicID() == Intrinsic::amdgcn_s_monitor_sleep);
220 const GCNSubtarget &
ST = TM.
getSubtarget<GCNSubtarget>(*
I.getFunction());
221 if (!
ST.hasNoSleepForever())
225 if (!(Sleep & 0x8000))
229 Value *NewSleep =
B.getInt16(0x2000);
230 I.setArgOperand(0, NewSleep);
237 AMDGPULowerIntrinsicsImpl Impl(M, TM);
243bool AMDGPULowerIntrinsicsLegacy::runOnModule(
Module &M) {
244 auto &TPC = getAnalysis<TargetPassConfig>();
247 AMDGPULowerIntrinsicsImpl Impl(M, TM);
251#define PASS_DESC "AMDGPU lower intrinsics"
258char AMDGPULowerIntrinsicsLegacy::ID = 0;
261 return new AMDGPULowerIntrinsicsLegacy;
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
The AMDGPU TargetMachine interface definition for hw codegen targets.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
AMD GCN specific subclass of TargetSubtarget.
uint64_t IntrinsicInst * II
ModuleAnalysisManager MAM
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
static bool forEachCall(Function &Intrin, T Callback)
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
LLVM_ABI void copyMetadata(const Instruction &SrcInst, ArrayRef< unsigned > WL=ArrayRef< unsigned >())
Copy metadata from SrcInst to this instruction.
A wrapper class for inspecting calls to intrinsic functions.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
A Module instance is used to store all the information related to an LLVM module.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
CodeGenOptLevel getOptLevel() const
Returns the optimization level: None, Less, Default, or Aggressive.
const STC & getSubtarget(const Function &F) const
This method returns a pointer to the specified type of TargetSubtargetInfo.
Target-Independent Code Generator Pass Configuration Options.
iterator_range< user_iterator > users()
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
ModulePass * createAMDGPULowerIntrinsicsLegacyPass()
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI Instruction * SplitBlockAndInsertIfThen(Value *Cond, BasicBlock::iterator SplitBefore, bool Unreachable, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, BasicBlock *ThenBlock=nullptr)
Split the containing block at the specified instruction - everything before SplitBefore stays in the ...
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)