Line data Source code
1 : //===-- AMDGPULowerIntrinsics.cpp -----------------------------------------===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 :
10 : #include "AMDGPU.h"
11 : #include "AMDGPUSubtarget.h"
12 : #include "llvm/CodeGen/TargetPassConfig.h"
13 : #include "llvm/Analysis/TargetTransformInfo.h"
14 : #include "llvm/IR/Constants.h"
15 : #include "llvm/IR/Instructions.h"
16 : #include "llvm/IR/IntrinsicInst.h"
17 : #include "llvm/IR/Module.h"
18 : #include "llvm/Transforms/Utils/LowerMemIntrinsics.h"
19 :
20 : #define DEBUG_TYPE "amdgpu-lower-intrinsics"
21 :
22 : using namespace llvm;
23 :
24 : namespace {
25 :
26 : const unsigned MaxStaticSize = 1024;
27 :
28 : class AMDGPULowerIntrinsics : public ModulePass {
29 : private:
30 : bool makeLIDRangeMetadata(Function &F) const;
31 :
32 : public:
33 : static char ID;
34 :
35 2248 : AMDGPULowerIntrinsics() : ModulePass(ID) {}
36 :
37 : bool runOnModule(Module &M) override;
38 : bool expandMemIntrinsicUses(Function &F);
39 0 : StringRef getPassName() const override {
40 0 : return "AMDGPU Lower Intrinsics";
41 : }
42 :
43 2231 : void getAnalysisUsage(AnalysisUsage &AU) const override {
44 : AU.addRequired<TargetTransformInfoWrapperPass>();
45 2231 : }
46 : };
47 :
48 : }
49 :
50 : char AMDGPULowerIntrinsics::ID = 0;
51 :
52 : char &llvm::AMDGPULowerIntrinsicsID = AMDGPULowerIntrinsics::ID;
53 :
54 199024 : INITIALIZE_PASS(AMDGPULowerIntrinsics, DEBUG_TYPE, "Lower intrinsics", false,
55 : false)
56 :
57 : // TODO: Should refine based on estimated number of accesses (e.g. does it
58 : // require splitting based on alignment)
59 : static bool shouldExpandOperationWithSize(Value *Size) {
60 : ConstantInt *CI = dyn_cast<ConstantInt>(Size);
61 93 : return !CI || (CI->getZExtValue() > MaxStaticSize);
62 : }
63 :
64 14 : bool AMDGPULowerIntrinsics::expandMemIntrinsicUses(Function &F) {
65 14 : Intrinsic::ID ID = F.getIntrinsicID();
66 : bool Changed = false;
67 :
68 113 : for (auto I = F.user_begin(), E = F.user_end(); I != E;) {
69 : Instruction *Inst = cast<Instruction>(*I);
70 : ++I;
71 :
72 99 : switch (ID) {
73 : case Intrinsic::memcpy: {
74 : auto *Memcpy = cast<MemCpyInst>(Inst);
75 : if (shouldExpandOperationWithSize(Memcpy->getLength())) {
76 7 : Function *ParentFunc = Memcpy->getParent()->getParent();
77 : const TargetTransformInfo &TTI =
78 7 : getAnalysis<TargetTransformInfoWrapperPass>().getTTI(*ParentFunc);
79 7 : expandMemCpyAsLoop(Memcpy, TTI);
80 : Changed = true;
81 7 : Memcpy->eraseFromParent();
82 : }
83 :
84 : break;
85 : }
86 : case Intrinsic::memmove: {
87 : auto *Memmove = cast<MemMoveInst>(Inst);
88 : if (shouldExpandOperationWithSize(Memmove->getLength())) {
89 1 : expandMemMoveAsLoop(Memmove);
90 : Changed = true;
91 1 : Memmove->eraseFromParent();
92 : }
93 :
94 : break;
95 : }
96 : case Intrinsic::memset: {
97 : auto *Memset = cast<MemSetInst>(Inst);
98 : if (shouldExpandOperationWithSize(Memset->getLength())) {
99 3 : expandMemSetAsLoop(Memset);
100 : Changed = true;
101 3 : Memset->eraseFromParent();
102 : }
103 :
104 : break;
105 : }
106 : default:
107 : break;
108 : }
109 : }
110 :
111 14 : return Changed;
112 : }
113 :
114 561 : bool AMDGPULowerIntrinsics::makeLIDRangeMetadata(Function &F) const {
115 561 : auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
116 561 : if (!TPC)
117 : return false;
118 :
119 561 : const TargetMachine &TM = TPC->getTM<TargetMachine>();
120 : bool Changed = false;
121 :
122 3771 : for (auto *U : F.users()) {
123 : auto *CI = dyn_cast<CallInst>(U);
124 : if (!CI)
125 : continue;
126 :
127 3210 : Changed |= AMDGPUSubtarget::get(TM, F).makeLIDRangeMetadata(CI);
128 : }
129 : return Changed;
130 : }
131 :
132 2230 : bool AMDGPULowerIntrinsics::runOnModule(Module &M) {
133 : bool Changed = false;
134 :
135 28240 : for (Function &F : M) {
136 26010 : if (!F.isDeclaration())
137 : continue;
138 :
139 4281 : switch (F.getIntrinsicID()) {
140 14 : case Intrinsic::memcpy:
141 : case Intrinsic::memmove:
142 : case Intrinsic::memset:
143 14 : if (expandMemIntrinsicUses(F))
144 : Changed = true;
145 : break;
146 :
147 561 : case Intrinsic::amdgcn_workitem_id_x:
148 : case Intrinsic::r600_read_tidig_x:
149 : case Intrinsic::amdgcn_workitem_id_y:
150 : case Intrinsic::r600_read_tidig_y:
151 : case Intrinsic::amdgcn_workitem_id_z:
152 : case Intrinsic::r600_read_tidig_z:
153 : case Intrinsic::r600_read_local_size_x:
154 : case Intrinsic::r600_read_local_size_y:
155 : case Intrinsic::r600_read_local_size_z:
156 561 : Changed |= makeLIDRangeMetadata(F);
157 561 : break;
158 :
159 : default:
160 : break;
161 : }
162 : }
163 :
164 2230 : return Changed;
165 : }
166 :
167 2246 : ModulePass *llvm::createAMDGPULowerIntrinsicsPass() {
168 2246 : return new AMDGPULowerIntrinsics();
169 : }
|