20#include "llvm/IR/IntrinsicsAMDGPU.h"
24#define DEBUG_TYPE "amdgpu-lower-intrinsics"
30class AMDGPULowerIntrinsicsImpl {
48class AMDGPULowerIntrinsicsLegacy :
public ModulePass {
52 AMDGPULowerIntrinsicsLegacy() :
ModulePass(ID) {}
54 bool runOnModule(
Module &M)
override;
70bool AMDGPULowerIntrinsicsImpl::run() {
74 switch (
F.getIntrinsicID()) {
77 case Intrinsic::amdgcn_s_barrier:
78 case Intrinsic::amdgcn_s_barrier_signal:
79 case Intrinsic::amdgcn_s_barrier_signal_isfirst:
80 case Intrinsic::amdgcn_s_barrier_wait:
81 case Intrinsic::amdgcn_s_cluster_barrier:
84 case Intrinsic::amdgcn_ptr_s_buffer_load:
86 F, [&](IntrinsicInst *
II) {
Changed |= visitPtrSBufferLoad(*
II); });
88 case Intrinsic::amdgcn_s_monitor_sleep:
90 F, [&](IntrinsicInst *
II) {
Changed |= visitMonitorSleep(*
II); });
92 case Intrinsic::amdgcn_cvt_scale_pk8_f16_fp8:
93 case Intrinsic::amdgcn_cvt_scale_pk8_bf16_fp8:
94 case Intrinsic::amdgcn_cvt_scale_pk8_f16_bf8:
95 case Intrinsic::amdgcn_cvt_scale_pk8_bf16_bf8:
96 case Intrinsic::amdgcn_cvt_scale_pk8_f16_fp4:
97 case Intrinsic::amdgcn_cvt_scale_pk8_bf16_fp4:
98 case Intrinsic::amdgcn_cvt_scale_pk8_f32_fp8:
99 case Intrinsic::amdgcn_cvt_scale_pk8_f32_bf8:
100 case Intrinsic::amdgcn_cvt_scale_pk8_f32_fp4:
101 case Intrinsic::amdgcn_cvt_scale_pk16_f16_bf6:
102 case Intrinsic::amdgcn_cvt_scale_pk16_bf16_bf6:
103 case Intrinsic::amdgcn_cvt_scale_pk16_f16_fp6:
104 case Intrinsic::amdgcn_cvt_scale_pk16_bf16_fp6:
105 case Intrinsic::amdgcn_cvt_scale_pk16_f32_fp6:
106 case Intrinsic::amdgcn_cvt_scale_pk16_f32_bf6:
109 case Intrinsic::amdgcn_wmma_f32_16x16x128_f8f6f4:
111 F, [&](IntrinsicInst *
II) {
Changed |= visitUnscaledWMMA(*
II); });
121bool AMDGPULowerIntrinsicsImpl::visitBarrier(IntrinsicInst &
I) {
122 assert(
I.getIntrinsicID() == Intrinsic::amdgcn_s_barrier ||
123 I.getIntrinsicID() == Intrinsic::amdgcn_s_barrier_signal ||
124 I.getIntrinsicID() == Intrinsic::amdgcn_s_barrier_signal_isfirst ||
125 I.getIntrinsicID() == Intrinsic::amdgcn_s_barrier_wait ||
126 I.getIntrinsicID() == Intrinsic::amdgcn_s_cluster_barrier);
128 const GCNSubtarget &
ST = TM.
getSubtarget<GCNSubtarget>(*
I.getFunction());
129 bool IsSingleWaveWG =
false;
132 IsSingleWaveWG =
ST.isSingleWavefrontWorkgroup(*
I.getFunction());
138 if (
I.getIntrinsicID() == Intrinsic::amdgcn_s_cluster_barrier) {
141 if (IsSingleWaveWG) {
142 B.CreateIntrinsicWithoutFolding(
B.getVoidTy(),
143 Intrinsic::amdgcn_wave_barrier, {})
148 CallInst *IsFirst =
B.CreateIntrinsicWithoutFolding(
149 B.getInt1Ty(), Intrinsic::amdgcn_s_barrier_signal_isfirst,
152 B.CreateIntrinsicWithoutFolding(
153 B.getVoidTy(), Intrinsic::amdgcn_s_barrier_wait, {BarrierID_16})
158 B.SetInsertPoint(ThenTerm);
165 B.CreateIntrinsicWithoutFolding(
166 B.getVoidTy(), Intrinsic::amdgcn_s_barrier_signal, {BarrierID_32})
169 B.SetInsertPoint(&
I);
170 B.CreateIntrinsicWithoutFolding(
171 B.getVoidTy(), Intrinsic::amdgcn_s_barrier_wait, {BarrierID_16})
178 bool IsWorkgroupScope =
false;
180 if (
I.getIntrinsicID() == Intrinsic::amdgcn_s_barrier_wait ||
181 I.getIntrinsicID() == Intrinsic::amdgcn_s_barrier_signal ||
182 I.getIntrinsicID() == Intrinsic::amdgcn_s_barrier_signal_isfirst) {
188 IsWorkgroupScope =
true;
189 else if (
I.getIntrinsicID() == Intrinsic::amdgcn_s_barrier_signal_isfirst &&
191 I.getContext().diagnose(
192 DiagnosticInfoUnsupported(*
I.getFunction(),
193 "s_barrier_signal_isfirst does not support "
194 "user_cluster_barrier_id (-3)",
198 assert(
I.getIntrinsicID() == Intrinsic::amdgcn_s_barrier);
199 IsWorkgroupScope =
true;
202 if (IsWorkgroupScope && IsSingleWaveWG) {
204 if (
I.getIntrinsicID() == Intrinsic::amdgcn_s_barrier ||
205 I.getIntrinsicID() == Intrinsic::amdgcn_s_barrier_wait) {
206 B.CreateIntrinsicWithoutFolding(
B.getVoidTy(),
207 Intrinsic::amdgcn_wave_barrier, {})
209 }
else if (
I.getIntrinsicID() ==
210 Intrinsic::amdgcn_s_barrier_signal_isfirst) {
212 I.replaceAllUsesWith(
B.getInt1(
true));
218 if (
I.getIntrinsicID() == Intrinsic::amdgcn_s_barrier &&
219 ST.hasSplitBarriers()) {
223 B.CreateIntrinsicWithoutFolding(
224 B.getVoidTy(), Intrinsic::amdgcn_s_barrier_signal, {BarrierID_32})
226 B.CreateIntrinsicWithoutFolding(
227 B.getVoidTy(), Intrinsic::amdgcn_s_barrier_wait, {BarrierID_16})
236bool AMDGPULowerIntrinsicsImpl::visitPtrSBufferLoad(IntrinsicInst &
I) {
237 assert(
I.getIntrinsicID() == Intrinsic::amdgcn_ptr_s_buffer_load);
239 if (
I.hasMetadata(LLVMContext::MD_invariant_load))
242 I.setMetadata(LLVMContext::MD_invariant_load,
247bool AMDGPULowerIntrinsicsImpl::visitMonitorSleep(IntrinsicInst &
I) {
248 assert(
I.getIntrinsicID() == Intrinsic::amdgcn_s_monitor_sleep);
250 const GCNSubtarget &
ST = TM.
getSubtarget<GCNSubtarget>(*
I.getFunction());
251 if (!
ST.hasNoSleepForever())
255 if (!(Sleep & 0x8000))
259 Value *NewSleep =
B.getInt16(127);
260 I.setArgOperand(0, NewSleep);
265bool AMDGPULowerIntrinsicsImpl::visitCvtScale(IntrinsicInst &
I) {
267 switch (
I.getIntrinsicID()) {
270 case Intrinsic::amdgcn_cvt_scale_pk8_f16_fp8:
271 case Intrinsic::amdgcn_cvt_scale_pk8_bf16_fp8:
272 case Intrinsic::amdgcn_cvt_scale_pk8_f16_bf8:
273 case Intrinsic::amdgcn_cvt_scale_pk8_bf16_bf8:
274 case Intrinsic::amdgcn_cvt_scale_pk8_f32_fp8:
275 case Intrinsic::amdgcn_cvt_scale_pk8_f32_bf8:
278 case Intrinsic::amdgcn_cvt_scale_pk8_f16_fp4:
279 case Intrinsic::amdgcn_cvt_scale_pk8_bf16_fp4:
280 case Intrinsic::amdgcn_cvt_scale_pk8_f32_fp4:
281 case Intrinsic::amdgcn_cvt_scale_pk16_f16_bf6:
282 case Intrinsic::amdgcn_cvt_scale_pk16_bf16_bf6:
283 case Intrinsic::amdgcn_cvt_scale_pk16_f16_fp6:
284 case Intrinsic::amdgcn_cvt_scale_pk16_bf16_fp6:
285 case Intrinsic::amdgcn_cvt_scale_pk16_f32_fp6:
286 case Intrinsic::amdgcn_cvt_scale_pk16_f32_bf6:
291 const GCNSubtarget &
ST = TM.
getSubtarget<GCNSubtarget>(*
I.getFunction());
292 if (
ST.hasBlock16ConversionScaleInsts())
296 if (ScaleSel < MaxSel)
299 I.getContext().diagnose(DiagnosticInfoUnsupported(
301 I.getCalledFunction()->getName() +
302 Twine(
" scale_sel maximum supported value is ") + Twine(MaxSel - 1),
308bool AMDGPULowerIntrinsicsImpl::visitUnscaledWMMA(IntrinsicInst &
I) {
309 assert(
I.getIntrinsicID() == Intrinsic::amdgcn_wmma_f32_16x16x128_f8f6f4);
311 const GCNSubtarget &
ST = TM.
getSubtarget<GCNSubtarget>(*
I.getFunction());
312 if (!
ST.hasGFX1250_STRICT())
319 Args.push_back(
B.getInt32(0));
322 Args.push_back(
B.getInt32(0));
323 Args.push_back(
B.getInt32(0));
326 Args.push_back(
B.getInt32(0));
327 Args.push_back(
B.getInt1(0));
328 Args.push_back(
B.getInt1(0));
330 CallInst *NewI =
B.CreateIntrinsicWithoutFolding(
331 I.getType(), Intrinsic::amdgcn_wmma_scale_f32_16x16x128_f8f6f4, Args);
332 I.replaceAllUsesWith(NewI);
342 AMDGPULowerIntrinsicsImpl Impl(M, TM);
348bool AMDGPULowerIntrinsicsLegacy::runOnModule(
Module &M) {
349 auto &TPC = getAnalysis<TargetPassConfig>();
352 AMDGPULowerIntrinsicsImpl Impl(M, TM);
356#define PASS_DESC "AMDGPU lower intrinsics"
363char AMDGPULowerIntrinsicsLegacy::ID = 0;
366 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()
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
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) -> IRBuilder< FolderTy, InserterTy >
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
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)