LLVM  9.0.0svn
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/Module.h"
18 
19 #define DEBUG_TYPE "amdgpu-lower-intrinsics"
20 
21 using namespace llvm;
22 
23 namespace {
24 
25 const unsigned MaxStaticSize = 1024;
26 
27 class AMDGPULowerIntrinsics : public ModulePass {
28 private:
29  bool makeLIDRangeMetadata(Function &F) const;
30 
31 public:
32  static char ID;
33 
34  AMDGPULowerIntrinsics() : ModulePass(ID) {}
35 
36  bool runOnModule(Module &M) override;
37  bool expandMemIntrinsicUses(Function &F);
38  StringRef getPassName() const override {
39  return "AMDGPU Lower Intrinsics";
40  }
41 
42  void getAnalysisUsage(AnalysisUsage &AU) const override {
44  }
45 };
46 
47 }
48 
50 
52 
53 INITIALIZE_PASS(AMDGPULowerIntrinsics, DEBUG_TYPE, "Lower intrinsics", false,
54  false)
55 
56 // TODO: Should refine based on estimated number of accesses (e.g. does it
57 // require splitting based on alignment)
58 static bool shouldExpandOperationWithSize(Value *Size) {
60  return !CI || (CI->getZExtValue() > MaxStaticSize);
61 }
62 
63 bool AMDGPULowerIntrinsics::expandMemIntrinsicUses(Function &F) {
65  bool Changed = false;
66 
67  for (auto I = F.user_begin(), E = F.user_end(); I != E;) {
68  Instruction *Inst = cast<Instruction>(*I);
69  ++I;
70 
71  switch (ID) {
72  case Intrinsic::memcpy: {
73  auto *Memcpy = cast<MemCpyInst>(Inst);
74  if (shouldExpandOperationWithSize(Memcpy->getLength())) {
75  Function *ParentFunc = Memcpy->getParent()->getParent();
76  const TargetTransformInfo &TTI =
77  getAnalysis<TargetTransformInfoWrapperPass>().getTTI(*ParentFunc);
78  expandMemCpyAsLoop(Memcpy, TTI);
79  Changed = true;
80  Memcpy->eraseFromParent();
81  }
82 
83  break;
84  }
85  case Intrinsic::memmove: {
86  auto *Memmove = cast<MemMoveInst>(Inst);
87  if (shouldExpandOperationWithSize(Memmove->getLength())) {
88  expandMemMoveAsLoop(Memmove);
89  Changed = true;
90  Memmove->eraseFromParent();
91  }
92 
93  break;
94  }
95  case Intrinsic::memset: {
96  auto *Memset = cast<MemSetInst>(Inst);
97  if (shouldExpandOperationWithSize(Memset->getLength())) {
98  expandMemSetAsLoop(Memset);
99  Changed = true;
100  Memset->eraseFromParent();
101  }
102 
103  break;
104  }
105  default:
106  break;
107  }
108  }
109 
110  return Changed;
111 }
112 
113 bool AMDGPULowerIntrinsics::makeLIDRangeMetadata(Function &F) const {
114  auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
115  if (!TPC)
116  return false;
117 
118  const TargetMachine &TM = TPC->getTM<TargetMachine>();
119  bool Changed = false;
120 
121  for (auto *U : F.users()) {
122  auto *CI = dyn_cast<CallInst>(U);
123  if (!CI)
124  continue;
125 
126  Changed |= AMDGPUSubtarget::get(TM, F).makeLIDRangeMetadata(CI);
127  }
128  return Changed;
129 }
130 
131 bool AMDGPULowerIntrinsics::runOnModule(Module &M) {
132  bool Changed = false;
133 
134  for (Function &F : M) {
135  if (!F.isDeclaration())
136  continue;
137 
138  switch (F.getIntrinsicID()) {
139  case Intrinsic::memcpy:
140  case Intrinsic::memmove:
141  case Intrinsic::memset:
142  if (expandMemIntrinsicUses(F))
143  Changed = true;
144  break;
145 
146  case Intrinsic::amdgcn_workitem_id_x:
147  case Intrinsic::r600_read_tidig_x:
148  case Intrinsic::amdgcn_workitem_id_y:
149  case Intrinsic::r600_read_tidig_y:
150  case Intrinsic::amdgcn_workitem_id_z:
151  case Intrinsic::r600_read_tidig_z:
152  case Intrinsic::r600_read_local_size_x:
153  case Intrinsic::r600_read_local_size_y:
154  case Intrinsic::r600_read_local_size_z:
155  Changed |= makeLIDRangeMetadata(F);
156  break;
157 
158  default:
159  break;
160  }
161  }
162 
163  return Changed;
164 }
165 
167  return new AMDGPULowerIntrinsics();
168 }
bool makeLIDRangeMetadata(Instruction *I) const
Creates value range metadata on an workitemid.* inrinsic call or load.
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:65
INITIALIZE_PASS(AMDGPULowerIntrinsics, DEBUG_TYPE, "Lower intrinsics", false, false) static bool shouldExpandOperationWithSize(Value *Size)
This class represents a function call, abstracting a target machine&#39;s calling convention.
F(f)
void expandMemSetAsLoop(MemSetInst *MemSet)
Expand MemSet as a loop. MemSet is not deleted.
static const AMDGPUSubtarget & get(const MachineFunction &MF)
AnalysisUsage & addRequired()
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
Definition: Constants.h:148
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:83
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.
Intrinsic::ID getIntrinsicID() const LLVM_READONLY
getIntrinsicID - This method returns the ID number of the specified function, or Intrinsic::not_intri...
Definition: Function.h:193
iterator_range< user_iterator > users()
Definition: Value.h:399
#define I(x, y, z)
Definition: MD5.cpp:58
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition: Pass.h:224
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Definition: Casting.h:332
uint32_t Size
Definition: Profile.cpp:46
char & AMDGPULowerIntrinsicsID
bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
Definition: Globals.cpp:227
user_iterator user_begin()
Definition: Value.h:375
Module * getParent()
Get the module that this global value is contained inside of...
Definition: GlobalValue.h:575
LLVM Value Representation.
Definition: Value.h:72
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:65
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
This pass exposes codegen information to IR-level passes.
void expandMemCpyAsLoop(MemCpyInst *MemCpy, const TargetTransformInfo &TTI)
Expand MemCpy as a loop. MemCpy is not deleted.
user_iterator user_end()
Definition: Value.h:383