LLVM  15.0.0git
PointerTypeAnalysis.cpp
Go to the documentation of this file.
1 //===- Target/DirectX/PointerTypeAnalisis.cpp - PointerType analysis ------===//
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 // Analysis pass to assign types to opaque pointers.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "PointerTypeAnalysis.h"
14 #include "llvm/IR/Instructions.h"
15 
16 using namespace llvm;
17 using namespace llvm::dxil;
18 
19 namespace {
20 
21 // Classifies the type of the value passed in by walking the value's users to
22 // find a typed instruction to materialize a type from.
23 TypedPointerType *classifyPointerType(const Value *V) {
25  "classifyPointerType called with non-opaque pointer");
26  Type *PointeeTy = nullptr;
27  if (auto *Inst = dyn_cast<GetElementPtrInst>(V)) {
28  if (!Inst->getResultElementType()->isOpaquePointerTy())
29  PointeeTy = Inst->getResultElementType();
30  } else if (auto *Inst = dyn_cast<AllocaInst>(V)) {
31  PointeeTy = Inst->getAllocatedType();
32  }
33  for (const auto *User : V->users()) {
34  Type *NewPointeeTy = nullptr;
35  if (const auto *Inst = dyn_cast<LoadInst>(User)) {
36  NewPointeeTy = Inst->getType();
37  } else if (const auto *Inst = dyn_cast<StoreInst>(User)) {
38  NewPointeeTy = Inst->getValueOperand()->getType();
39  } else if (const auto *Inst = dyn_cast<GetElementPtrInst>(User)) {
40  NewPointeeTy = Inst->getSourceElementType();
41  }
42  if (NewPointeeTy) {
43  // HLSL doesn't support pointers, so it is unlikely to get more than one
44  // or two levels of indirection in the IR. Because of this, recursion is
45  // pretty safe.
46  if (NewPointeeTy->isOpaquePointerTy())
47  return TypedPointerType::get(classifyPointerType(User),
49  if (!PointeeTy)
50  PointeeTy = NewPointeeTy;
51  else if (PointeeTy != NewPointeeTy)
52  PointeeTy = Type::getInt8Ty(V->getContext());
53  }
54  }
55  // If we were unable to determine the pointee type, set to i8
56  if (!PointeeTy)
57  PointeeTy = Type::getInt8Ty(V->getContext());
58  return TypedPointerType::get(PointeeTy,
60 }
61 
62 // This function constructs a function type accepting typed pointers. It only
63 // handles function arguments and return types, and assigns the function type to
64 // the function's value in the type map.
65 void classifyFunctionType(const Function &F, PointerTypeMap &Map) {
66  SmallVector<Type *, 8> NewArgs;
67  bool HasOpaqueTy = false;
68  Type *RetTy = F.getReturnType();
69  if (RetTy->isOpaquePointerTy()) {
70  RetTy = nullptr;
71  for (const auto &B : F) {
72  for (const auto &I : B) {
73  if (const auto *RetInst = dyn_cast_or_null<ReturnInst>(&I)) {
74  Type *NewRetTy = classifyPointerType(RetInst->getReturnValue());
75  if (!RetTy)
76  RetTy = NewRetTy;
77  else if (RetTy != NewRetTy)
78  RetTy = TypedPointerType::get(
79  Type::getInt8Ty(I.getContext()),
80  F.getReturnType()->getPointerAddressSpace());
81  }
82  }
83  }
84  }
85  for (auto &A : F.args()) {
86  Type *ArgTy = A.getType();
87  if (ArgTy->isOpaquePointerTy()) {
88  TypedPointerType *NewTy = classifyPointerType(&A);
89  Map[&A] = NewTy;
90  ArgTy = NewTy;
91  HasOpaqueTy = true;
92  }
93  NewArgs.push_back(ArgTy);
94  }
95  if (!HasOpaqueTy)
96  return;
97  Map[&F] = FunctionType::get(RetTy, NewArgs, false);
98 }
99 } // anonymous namespace
100 
102  PointerTypeMap Map;
103  for (auto &G : M.globals()) {
104  if (G.getType()->isOpaquePointerTy())
105  Map[&G] = classifyPointerType(&G);
106  }
107  for (auto &F : M) {
108  classifyFunctionType(F, Map);
109 
110  for (const auto &B : F) {
111  for (const auto &I : B) {
112  if (I.getType()->isOpaquePointerTy())
113  Map[&I] = classifyPointerType(&I);
114  }
115  }
116  }
117 
118  return Map;
119 }
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
M
We currently emits eax Perhaps this is what we really should generate is Is imull three or four cycles eax eax The current instruction priority is based on pattern complexity The former is more complex because it folds a load so the latter will not be emitted Perhaps we should use AddedComplexity to give LEA32r a higher priority We should always try to match LEA first since the LEA matching code does some estimate to determine whether the match is profitable if we care more about code then imull is better It s two bytes shorter than movl leal On a Pentium M
Definition: README.txt:252
llvm::Function
Definition: Function.h:60
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1185
llvm::Type::getPointerAddressSpace
unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
Definition: DerivedTypes.h:729
llvm::FunctionType::get
static FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
Definition: Type.cpp:361
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
llvm::Type::getInt8Ty
static IntegerType * getInt8Ty(LLVMContext &C)
Definition: Type.cpp:237
F
#define F(x, y, z)
Definition: MD5.cpp:55
PointerTypeAnalysis.h
llvm::msgpack::Type::Map
@ Map
llvm::User
Definition: User.h:44
llvm::ARM_PROC::A
@ A
Definition: ARMBaseInfo.h:34
B
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
llvm::dxil::TypedPointerType
Definition: DXILPointerType.h:22
llvm::dxil::PointerTypeAnalysis::run
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
Definition: PointerTypeAnalysis.cpp:101
G
const DataFlowGraph & G
Definition: RDFGraph.cpp:200
llvm::dxil
Definition: DXILPointerType.h:18
llvm::DenseMap< const Value *, Type * >
I
#define I(x, y, z)
Definition: MD5.cpp:58
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::Module
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
llvm::Value::getType
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:255
llvm::Value::getContext
LLVMContext & getContext() const
All values hold a context through their type.
Definition: Value.cpp:991
llvm::Type::isOpaquePointerTy
bool isOpaquePointerTy() const
True if this is an instance of an opaque PointerType.
Definition: Type.cpp:61
Instructions.h
llvm::Value
LLVM Value Representation.
Definition: Value.h:74
llvm::Value::users
iterator_range< user_iterator > users()
Definition: Value.h:421
llvm::dxil::TypedPointerType::get
static TypedPointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space.
Definition: DXILPointerType.cpp:29