]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/llvm/lib/Target/AMDGPU/AMDGPULowerIntrinsics.cpp
zfs: merge openzfs/zfs@eb62221ff (zfs-2.1-release) into stable/13
[FreeBSD/FreeBSD.git] / contrib / llvm-project / llvm / lib / Target / AMDGPU / AMDGPULowerIntrinsics.cpp
1 //===-- AMDGPULowerIntrinsics.cpp -----------------------------------------===//
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 #include "AMDGPU.h"
10 #include "AMDGPUSubtarget.h"
11 #include "llvm/Analysis/TargetTransformInfo.h"
12 #include "llvm/CodeGen/TargetPassConfig.h"
13 #include "llvm/IR/Constants.h"
14 #include "llvm/IR/Instructions.h"
15 #include "llvm/IR/IntrinsicInst.h"
16 #include "llvm/IR/IntrinsicsR600.h"
17 #include "llvm/IR/Module.h"
18 #include "llvm/Support/CommandLine.h"
19 #include "llvm/Target/TargetMachine.h"
20 #include "llvm/Transforms/Utils/LowerMemIntrinsics.h"
21
22 #define DEBUG_TYPE "amdgpu-lower-intrinsics"
23
24 using namespace llvm;
25
26 namespace {
27
28 static int MaxStaticSize;
29
30 static cl::opt<int, true> MemIntrinsicExpandSizeThresholdOpt(
31   "amdgpu-mem-intrinsic-expand-size",
32   cl::desc("Set minimum mem intrinsic size to expand in IR"),
33   cl::location(MaxStaticSize),
34   cl::init(1024),
35   cl::Hidden);
36
37
38 class AMDGPULowerIntrinsics : public ModulePass {
39 private:
40   bool makeLIDRangeMetadata(Function &F) const;
41
42 public:
43   static char ID;
44
45   AMDGPULowerIntrinsics() : ModulePass(ID) {}
46
47   bool runOnModule(Module &M) override;
48   bool expandMemIntrinsicUses(Function &F);
49   StringRef getPassName() const override {
50     return "AMDGPU Lower Intrinsics";
51   }
52
53   void getAnalysisUsage(AnalysisUsage &AU) const override {
54     AU.addRequired<TargetTransformInfoWrapperPass>();
55   }
56 };
57
58 }
59
60 char AMDGPULowerIntrinsics::ID = 0;
61
62 char &llvm::AMDGPULowerIntrinsicsID = AMDGPULowerIntrinsics::ID;
63
64 INITIALIZE_PASS(AMDGPULowerIntrinsics, DEBUG_TYPE, "Lower intrinsics", false,
65                 false)
66
67 // TODO: Should refine based on estimated number of accesses (e.g. does it
68 // require splitting based on alignment)
69 static bool shouldExpandOperationWithSize(Value *Size) {
70   ConstantInt *CI = dyn_cast<ConstantInt>(Size);
71   return !CI || (CI->getSExtValue() > MaxStaticSize);
72 }
73
74 bool AMDGPULowerIntrinsics::expandMemIntrinsicUses(Function &F) {
75   Intrinsic::ID ID = F.getIntrinsicID();
76   bool Changed = false;
77
78   for (User *U : llvm::make_early_inc_range(F.users())) {
79     Instruction *Inst = cast<Instruction>(U);
80
81     switch (ID) {
82     case Intrinsic::memcpy: {
83       auto *Memcpy = cast<MemCpyInst>(Inst);
84       if (shouldExpandOperationWithSize(Memcpy->getLength())) {
85         Function *ParentFunc = Memcpy->getParent()->getParent();
86         const TargetTransformInfo &TTI =
87             getAnalysis<TargetTransformInfoWrapperPass>().getTTI(*ParentFunc);
88         expandMemCpyAsLoop(Memcpy, TTI);
89         Changed = true;
90         Memcpy->eraseFromParent();
91       }
92
93       break;
94     }
95     case Intrinsic::memmove: {
96       auto *Memmove = cast<MemMoveInst>(Inst);
97       if (shouldExpandOperationWithSize(Memmove->getLength())) {
98         expandMemMoveAsLoop(Memmove);
99         Changed = true;
100         Memmove->eraseFromParent();
101       }
102
103       break;
104     }
105     case Intrinsic::memset: {
106       auto *Memset = cast<MemSetInst>(Inst);
107       if (shouldExpandOperationWithSize(Memset->getLength())) {
108         expandMemSetAsLoop(Memset);
109         Changed = true;
110         Memset->eraseFromParent();
111       }
112
113       break;
114     }
115     default:
116       break;
117     }
118   }
119
120   return Changed;
121 }
122
123 bool AMDGPULowerIntrinsics::makeLIDRangeMetadata(Function &F) const {
124   auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
125   if (!TPC)
126     return false;
127
128   const TargetMachine &TM = TPC->getTM<TargetMachine>();
129   bool Changed = false;
130
131   for (auto *U : F.users()) {
132     auto *CI = dyn_cast<CallInst>(U);
133     if (!CI)
134       continue;
135
136     Function *Caller = CI->getParent()->getParent();
137     const AMDGPUSubtarget &ST = AMDGPUSubtarget::get(TM, *Caller);
138     Changed |= ST.makeLIDRangeMetadata(CI);
139   }
140   return Changed;
141 }
142
143 bool AMDGPULowerIntrinsics::runOnModule(Module &M) {
144   bool Changed = false;
145
146   for (Function &F : M) {
147     if (!F.isDeclaration())
148       continue;
149
150     switch (F.getIntrinsicID()) {
151     case Intrinsic::memcpy:
152     case Intrinsic::memmove:
153     case Intrinsic::memset:
154       if (expandMemIntrinsicUses(F))
155         Changed = true;
156       break;
157
158     case Intrinsic::r600_read_tidig_x:
159     case Intrinsic::r600_read_tidig_y:
160     case Intrinsic::r600_read_tidig_z:
161     case Intrinsic::r600_read_local_size_x:
162     case Intrinsic::r600_read_local_size_y:
163     case Intrinsic::r600_read_local_size_z:
164       Changed |= makeLIDRangeMetadata(F);
165       break;
166
167     default:
168       break;
169     }
170   }
171
172   return Changed;
173 }
174
175 ModulePass *llvm::createAMDGPULowerIntrinsicsPass() {
176   return new AMDGPULowerIntrinsics();
177 }