forked from JuliaLang/julia
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathllvm-alloc-helpers.h
145 lines (129 loc) · 4.76 KB
/
llvm-alloc-helpers.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// This file is a part of Julia. License is MIT: https://julialang.org/license
#ifndef LLVM_ALLOC_HELPERS_H
#define LLVM_ALLOC_HELPERS_H
#include <llvm-c/Types.h>
#include <llvm/ADT/SmallSet.h>
#include <llvm/ADT/SmallVector.h>
#include <llvm/IR/Instructions.h>
#include <utility>
#include <map>
#include "llvm-pass-helpers.h"
namespace jl_alloc {
struct CheckInst {
struct Frame {
llvm::Instruction *parent;
uint32_t offset;
llvm::Instruction::use_iterator use_it;
llvm::Instruction::use_iterator use_end;
};
typedef llvm::SmallVector<Frame,4> Stack;
};
struct MemOp {
llvm::Instruction *inst;
uint64_t offset = 0;
unsigned opno;
uint32_t size = 0;
bool isobjref:1;
bool isaggr:1;
MemOp(llvm::Instruction *inst, unsigned opno)
: inst(inst),
opno(opno),
isobjref(false),
isaggr(false)
{}
};
struct Field {
uint32_t size;
bool hasobjref:1;
bool hasaggr:1;
bool multiloc:1;
bool hasload:1;
llvm::Type *elty;
llvm::SmallVector<MemOp,4> accesses;
Field(uint32_t size, llvm::Type *elty)
: size(size),
hasobjref(false),
hasaggr(false),
multiloc(false),
hasload(false),
elty(elty)
{
}
};
struct AllocUseInfo {
llvm::SmallSet<llvm::Instruction*,16> uses;
llvm::SmallSet<llvm::CallInst*,4> preserves;
std::map<uint32_t,Field> memops;
// Completely unknown use
bool escaped:1;
// Address is leaked to functions that doesn't care where the object is allocated.
bool addrescaped:1;
// There are reader of the memory
bool hasload:1;
// There are uses in gc_preserve intrinsics or ccall roots
bool haspreserve:1;
// There are objects fields being loaded
bool refload:1;
// There are objects fields being stored
bool refstore:1;
// There are typeof call
// This can be optimized without optimizing out the allocation itself
bool hastypeof:1;
// There are store/load/memset on this object with offset or size (or value for memset)
// that cannot be statically computed.
// This is a weaker form of `addrescaped` since `hasload` can still be used
// to see if the memory is actually being used
bool hasunknownmem:1;
// The object is returned
bool returned:1;
// The object is used in an error function
bool haserror:1;
void reset()
{
escaped = false;
addrescaped = false;
hasload = false;
haspreserve = false;
refload = false;
refstore = false;
hastypeof = false;
hasunknownmem = false;
returned = false;
haserror = false;
uses.clear();
preserves.clear();
memops.clear();
}
void dump();
bool addMemOp(llvm::Instruction *inst, unsigned opno, uint32_t offset, llvm::Type *elty,
bool isstore, const llvm::DataLayout &DL);
std::pair<const uint32_t,Field> &getField(uint32_t offset, uint32_t size, llvm::Type *elty);
std::map<uint32_t,Field>::iterator findLowerField(uint32_t offset)
{
// Find the last field that starts no higher than `offset`.
auto it = memops.upper_bound(offset);
if (it != memops.begin())
return --it;
return memops.end();
}
};
struct EscapeAnalysisRequiredArgs {
AllocUseInfo &use_info; // The returned escape analysis data
CheckInst::Stack &check_stack; // A preallocated stack to be used for escape analysis
JuliaPassContext &pass; // The current optimization pass (for accessing intrinsic functions)
const llvm::DataLayout &DL; // The module's data layout (for handling GEPs/memory operations)
};
struct EscapeAnalysisOptionalArgs {
//A set of basic blocks to run escape analysis over. Uses outside these basic blocks
//will not be considered. Defaults to nullptr, which means all uses of the allocation
//are considered
const llvm::SmallPtrSetImpl<const llvm::BasicBlock*> *valid_set;
EscapeAnalysisOptionalArgs() = default;
EscapeAnalysisOptionalArgs &with_valid_set(decltype(valid_set) valid_set) {
this->valid_set = valid_set;
return *this;
}
};
void runEscapeAnalysis(llvm::Instruction *I, EscapeAnalysisRequiredArgs required, EscapeAnalysisOptionalArgs options=EscapeAnalysisOptionalArgs());
}
#endif