LLVM  12.0.0git
AMDGPULowerIntrinsics.cpp
Go to the documentation of this file.
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"
13 #include "llvm/IR/Constants.h"
14 #include "llvm/IR/Instructions.h"
15 #include "llvm/IR/IntrinsicInst.h"
16 #include "llvm/IR/IntrinsicsAMDGPU.h"
17 #include "llvm/IR/IntrinsicsR600.h"
18 #include "llvm/IR/Module.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 {
55  }
56 };
57 
58 }
59 
61 
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 (auto I = F.user_begin(), E = F.user_end(); I != E;) {
79  Instruction *Inst = cast<Instruction>(*I);
80  ++I;
81 
82  switch (ID) {
83  case Intrinsic::memcpy: {
84  auto *Memcpy = cast<MemCpyInst>(Inst);
85  if (shouldExpandOperationWithSize(Memcpy->getLength())) {
86  Function *ParentFunc = Memcpy->getParent()->getParent();
87  const TargetTransformInfo &TTI =
88  getAnalysis<TargetTransformInfoWrapperPass>().getTTI(*ParentFunc);
89  expandMemCpyAsLoop(Memcpy, TTI);
90  Changed = true;
91  Memcpy->eraseFromParent();
92  }
93 
94  break;
95  }
96  case Intrinsic::memmove: {
97  auto *Memmove = cast<MemMoveInst>(Inst);
98  if (shouldExpandOperationWithSize(Memmove->getLength())) {
99  expandMemMoveAsLoop(Memmove);
100  Changed = true;
101  Memmove->eraseFromParent();
102  }
103 
104  break;
105  }
106  case Intrinsic::memset: {
107  auto *Memset = cast<MemSetInst>(Inst);
108  if (shouldExpandOperationWithSize(Memset->getLength())) {
109  expandMemSetAsLoop(Memset);
110  Changed = true;
111  Memset->eraseFromParent();
112  }
113 
114  break;
115  }
116  default:
117  break;
118  }
119  }
120 
121  return Changed;
122 }
123 
124 bool AMDGPULowerIntrinsics::makeLIDRangeMetadata(Function &F) const {
125  auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
126  if (!TPC)
127  return false;
128 
129  const TargetMachine &TM = TPC->getTM<TargetMachine>();
130  bool Changed = false;
131 
132  for (auto *U : F.users()) {
133  auto *CI = dyn_cast<CallInst>(U);
134  if (!CI)
135  continue;
136 
137  Function *Caller = CI->getParent()->getParent();
138  const AMDGPUSubtarget &ST = AMDGPUSubtarget::get(TM, *Caller);
139  Changed |= ST.makeLIDRangeMetadata(CI);
140  }
141  return Changed;
142 }
143 
144 bool AMDGPULowerIntrinsics::runOnModule(Module &M) {
145  bool Changed = false;
146 
147  for (Function &F : M) {
148  if (!F.isDeclaration())
149  continue;
150 
151  switch (F.getIntrinsicID()) {
152  case Intrinsic::memcpy:
153  case Intrinsic::memmove:
154  case Intrinsic::memset:
155  if (expandMemIntrinsicUses(F))
156  Changed = true;
157  break;
158 
159  case Intrinsic::amdgcn_workitem_id_x:
160  case Intrinsic::r600_read_tidig_x:
161  case Intrinsic::amdgcn_workitem_id_y:
162  case Intrinsic::r600_read_tidig_y:
163  case Intrinsic::amdgcn_workitem_id_z:
164  case Intrinsic::r600_read_tidig_z:
165  case Intrinsic::r600_read_local_size_x:
166  case Intrinsic::r600_read_local_size_y:
167  case Intrinsic::r600_read_local_size_z:
168  Changed |= makeLIDRangeMetadata(F);
169  break;
170 
171  default:
172  break;
173  }
174  }
175 
176  return Changed;
177 }
178 
180  return new AMDGPULowerIntrinsics();
181 }
AMDGPU specific subclass of TargetSubtarget.
This class represents lattice values for constants.
Definition: AllocatorList.h:23
void expandMemMoveAsLoop(MemMoveInst *MemMove)
Expand MemMove as a loop. MemMove is not deleted.
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:67
INITIALIZE_PASS(AMDGPULowerIntrinsics, DEBUG_TYPE, "Lower intrinsics", false, false) static bool shouldExpandOperationWithSize(Value *Size)
F(f)
void expandMemSetAsLoop(MemSetInst *MemSet)
Expand MemSet as a loop. MemSet is not deleted.
static const AMDGPUSubtarget & get(const MachineFunction &MF)
AnalysisUsage & addRequired()
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:427
Wrapper pass for TargetTransformInfo.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Represent the analysis usage information of a pass.
ModulePass * createAMDGPULowerIntrinsicsPass()
#define DEBUG_TYPE
This is the shared class of boolean and integer constants.
Definition: Constants.h:77
This pass provides access to the codegen interfaces that are needed for IR-level transformations.
Module.h This file contains the declarations for the Module class.
#define I(x, y, z)
Definition: MD5.cpp:59
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition: Pass.h:238
char & AMDGPULowerIntrinsicsID
Module * getParent()
Get the module that this global value is contained inside of...
Definition: GlobalValue.h:572
LLVM Value Representation.
Definition: Value.h:75
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:77
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
This pass exposes codegen information to IR-level passes.
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
Definition: Constants.h:152
LocationClass< Ty > location(Ty &L)
Definition: CommandLine.h:443
void expandMemCpyAsLoop(MemCpyInst *MemCpy, const TargetTransformInfo &TTI)
Expand MemCpy as a loop. MemCpy is not deleted.