blob: dcb6670621eef25a49e565b81d90b3c085a7c712 [file] [log] [blame]
Matt Arsenault0699ef32017-02-09 22:00:42 +00001//===-- 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"
Stanislav Mekhanoshinc90347d2017-04-12 20:48:56 +000011#include "AMDGPUSubtarget.h"
Matt Arsenault0699ef32017-02-09 22:00:42 +000012#include "llvm/IR/Constants.h"
13#include "llvm/IR/Instructions.h"
14#include "llvm/IR/IntrinsicInst.h"
15#include "llvm/IR/Module.h"
16#include "llvm/Transforms/Utils/LowerMemIntrinsics.h"
17
18#define DEBUG_TYPE "amdgpu-lower-intrinsics"
19
20using namespace llvm;
21
22namespace {
23
24const unsigned MaxStaticSize = 1024;
25
26class AMDGPULowerIntrinsics : public ModulePass {
Stanislav Mekhanoshinc90347d2017-04-12 20:48:56 +000027private:
28 const TargetMachine *TM;
29
30 bool makeLIDRangeMetadata(Function &F) const;
31
Matt Arsenault0699ef32017-02-09 22:00:42 +000032public:
33 static char ID;
34
Stanislav Mekhanoshinc90347d2017-04-12 20:48:56 +000035 AMDGPULowerIntrinsics(const TargetMachine *TM = nullptr)
36 : ModulePass(ID), TM(TM) { }
Matt Arsenault0699ef32017-02-09 22:00:42 +000037 bool runOnModule(Module &M) override;
38 StringRef getPassName() const override {
39 return "AMDGPU Lower Intrinsics";
40 }
41};
42
43}
44
45char AMDGPULowerIntrinsics::ID = 0;
46
47char &llvm::AMDGPULowerIntrinsicsID = AMDGPULowerIntrinsics::ID;
48
Stanislav Mekhanoshinc90347d2017-04-12 20:48:56 +000049INITIALIZE_TM_PASS(AMDGPULowerIntrinsics, DEBUG_TYPE,
50 "Lower intrinsics", false, false)
Matt Arsenault0699ef32017-02-09 22:00:42 +000051
52// TODO: Should refine based on estimated number of accesses (e.g. does it
53// require splitting based on alignment)
54static bool shouldExpandOperationWithSize(Value *Size) {
55 ConstantInt *CI = dyn_cast<ConstantInt>(Size);
56 return !CI || (CI->getZExtValue() > MaxStaticSize);
57}
58
59static bool expandMemIntrinsicUses(Function &F) {
60 Intrinsic::ID ID = F.getIntrinsicID();
NAKAMURA Takumi022c6e42017-02-12 13:15:31 +000061 bool Changed = false;
Matt Arsenault0699ef32017-02-09 22:00:42 +000062
63 for (auto I = F.user_begin(), E = F.user_end(); I != E;) {
64 Instruction *Inst = cast<Instruction>(*I);
65 ++I;
66
67 switch (ID) {
68 case Intrinsic::memcpy: {
69 auto *Memcpy = cast<MemCpyInst>(Inst);
70 if (shouldExpandOperationWithSize(Memcpy->getLength())) {
71 expandMemCpyAsLoop(Memcpy);
72 Changed = true;
73 Memcpy->eraseFromParent();
74 }
75
76 break;
77 }
78 case Intrinsic::memmove: {
79 auto *Memmove = cast<MemMoveInst>(Inst);
80 if (shouldExpandOperationWithSize(Memmove->getLength())) {
81 expandMemMoveAsLoop(Memmove);
82 Changed = true;
83 Memmove->eraseFromParent();
84 }
85
86 break;
87 }
88 case Intrinsic::memset: {
89 auto *Memset = cast<MemSetInst>(Inst);
90 if (shouldExpandOperationWithSize(Memset->getLength())) {
91 expandMemSetAsLoop(Memset);
92 Changed = true;
93 Memset->eraseFromParent();
94 }
95
96 break;
97 }
98 default:
99 break;
100 }
101 }
102
103 return Changed;
104}
105
Stanislav Mekhanoshinc90347d2017-04-12 20:48:56 +0000106bool AMDGPULowerIntrinsics::makeLIDRangeMetadata(Function &F) const {
107 if (!TM)
108 return false;
109
110 bool Changed = false;
111 const AMDGPUSubtarget &ST = TM->getSubtarget<AMDGPUSubtarget>(F);
112
113 for (auto *U : F.users()) {
114 auto *CI = dyn_cast<CallInst>(U);
115 if (!CI)
116 continue;
117
118 Changed |= ST.makeLIDRangeMetadata(CI);
119 }
120 return Changed;
121}
122
Matt Arsenault0699ef32017-02-09 22:00:42 +0000123bool AMDGPULowerIntrinsics::runOnModule(Module &M) {
124 bool Changed = false;
125
126 for (Function &F : M) {
127 if (!F.isDeclaration())
128 continue;
129
130 switch (F.getIntrinsicID()) {
131 case Intrinsic::memcpy:
132 case Intrinsic::memmove:
133 case Intrinsic::memset:
134 if (expandMemIntrinsicUses(F))
135 Changed = true;
136 break;
Stanislav Mekhanoshinc90347d2017-04-12 20:48:56 +0000137
138 case Intrinsic::amdgcn_workitem_id_x:
139 case Intrinsic::r600_read_tidig_x:
140 case Intrinsic::amdgcn_workitem_id_y:
141 case Intrinsic::r600_read_tidig_y:
142 case Intrinsic::amdgcn_workitem_id_z:
143 case Intrinsic::r600_read_tidig_z:
144 case Intrinsic::r600_read_local_size_x:
145 case Intrinsic::r600_read_local_size_y:
146 case Intrinsic::r600_read_local_size_z:
147 Changed |= makeLIDRangeMetadata(F);
148 break;
149
Matt Arsenault0699ef32017-02-09 22:00:42 +0000150 default:
151 break;
152 }
153 }
154
155 return Changed;
156}
157
Stanislav Mekhanoshinc90347d2017-04-12 20:48:56 +0000158ModulePass *llvm::createAMDGPULowerIntrinsicsPass(const TargetMachine *TM) {
159 return new AMDGPULowerIntrinsics(TM);
Matt Arsenault0699ef32017-02-09 22:00:42 +0000160}