LLVM: lib/IR/DIExpressionOptimizer.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
16
17using namespace llvm;
18
19
21 if (Op.getOp() == dwarf::DW_OP_constu)
22 return Op.getArg(0);
23 return std::nullopt;
24}
25
26
28 switch (Op) {
29 case dwarf::DW_OP_plus:
30 case dwarf::DW_OP_minus:
31 case dwarf::DW_OP_shl:
32 case dwarf::DW_OP_shr:
33 return Val == 0;
34 case dwarf::DW_OP_mul:
35 case dwarf::DW_OP_div:
36 return Val == 1;
37 default:
38 return false;
39 }
40}
41
42
43
44static std::optional<uint64_t>
47
48 bool ResultOverflowed;
50 case dwarf::DW_OP_plus: {
51 auto Result = SaturatingAdd(Const1, Const2, &ResultOverflowed);
52 if (ResultOverflowed)
53 return std::nullopt;
54 return Result;
55 }
56 case dwarf::DW_OP_minus: {
57 if (Const1 < Const2)
58 return std::nullopt;
59 return Const1 - Const2;
60 }
61 case dwarf::DW_OP_shl: {
62 if (Const2 >= std::numeric_limits<uint64_t>::digits ||
64 return std::nullopt;
65 return Const1 << Const2;
66 }
67 case dwarf::DW_OP_shr: {
68 if (Const2 >= std::numeric_limits<uint64_t>::digits ||
70 return std::nullopt;
71 return Const1 >> Const2;
72 }
73 case dwarf::DW_OP_mul: {
75 if (ResultOverflowed)
76 return std::nullopt;
77 return Result;
78 }
79 case dwarf::DW_OP_div: {
80 if (Const2)
81 return Const1 / Const2;
82 return std::nullopt;
83 }
84 default:
85 return std::nullopt;
86 }
87}
88
89
90
93 return Operator1 == Operator2 &&
94 (Operator1 == dwarf::DW_OP_plus || Operator1 == dwarf::DW_OP_mul);
95}
96
97
100 Cursor.consume(1);
102}
103
104
107 Cursor.assignNewExpr(WorkingOps);
109}
110
111
112
113
119 while (Loc < WorkingOps.size()) {
120 auto Op = Cursor.peek();
121
122 if ()
123 break;
124 auto OpRaw = Op->getOp();
125
126 if (OpRaw >= dwarf::DW_OP_lit0 && OpRaw <= dwarf::DW_OP_lit31) {
127 ResultOps.push_back(dwarf::DW_OP_constu);
128 ResultOps.push_back(OpRaw - dwarf::DW_OP_lit0);
130 continue;
131 }
132 if (OpRaw == dwarf::DW_OP_plus_uconst) {
133 ResultOps.push_back(dwarf::DW_OP_constu);
135 ResultOps.push_back(dwarf::DW_OP_plus);
137 continue;
138 }
141 ResultOps.append(WorkingOps.begin() + PrevLoc, WorkingOps.begin() + Loc);
142 }
143 return ResultOps;
144}
145
146
147
148
154 while (Loc < WorkingOps.size()) {
155 auto Op1 = Cursor.peek();
156
157 if (!Op1)
158 break;
159 auto Op1Raw = Op1->getOp();
160
161 if (Op1Raw == dwarf::DW_OP_constu && Op1->getArg(0) == 0) {
162 ResultOps.push_back(dwarf::DW_OP_lit0);
164 continue;
165 }
166
167 auto Op2 = Cursor.peekNext();
168
169 if (!Op2) {
172 ResultOps.append(WorkingOps.begin() + PrevLoc, WorkingOps.begin() + Loc);
173 break;
174 }
175 auto Op2Raw = Op2->getOp();
176
177 if (Op1Raw == dwarf::DW_OP_constu && Op2Raw == dwarf::DW_OP_plus) {
178 ResultOps.push_back(dwarf::DW_OP_plus_uconst);
179 ResultOps.push_back(Op1->getArg(0));
182 continue;
183 }
186 ResultOps.append(WorkingOps.begin() + PrevLoc, WorkingOps.begin() + Loc);
187 }
188 return ResultOps;
189}
190
191
192
197
201 return true;
202 }
203 return false;
204}
205
206
207
208
213
215 if (!Const2)
216 return false;
217
220 if (!Result) {
222 return true;
223 }
225 WorkingOps[Loc] = dwarf::DW_OP_constu;
226 WorkingOps[Loc + 1] = *Result;
228 return true;
229}
230
231
232
233
238
242
244 return false;
245
247 if (!Result) {
249 return true;
250 }
252 WorkingOps[Loc] = dwarf::DW_OP_constu;
253 WorkingOps[Loc + 1] = *Result;
255 return true;
256}
257
258
259
260
261
265
270
274 return false;
275
277 if (!Result) {
279 return true;
280 }
282 WorkingOps[Loc] = dwarf::DW_OP_constu;
283 WorkingOps[Loc + 1] = *Result;
285 return true;
286}
287
289
295
296
297
298 while (Loc < ResultOps.size()) {
299 Ops.clear();
300
301 auto Op = Cursor.peek();
302
303 if ()
304 break;
305
307
308 if (!Const1) {
309
311 continue;
312 }
313
315
316 Op = Cursor.peekNext();
317
318 if ()
319 break;
320
322
323
325 continue;
326
327 Op = Cursor.peekNextN(2);
328
329 if () {
331 continue;
332 }
333
335
336
338 continue;
339
340 Op = Cursor.peekNextN(3);
341
342 if () {
344 continue;
345 }
346
348
349
351 continue;
352
353 Op = Cursor.peekNextN(4);
354 if () {
356 continue;
357 }
358
360 Op = Cursor.peekNextN(5);
361 if () {
363 continue;
364 }
365
367
368
369
371 ResultOps))
372 continue;
373
375 }
378 assert(Result->isValid() && "concatenated expression is not valid");
379 return Result;
380}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool tryFoldNoOpMath(uint64_t Const1, ArrayRef< DIExpression::ExprOperand > Ops, uint64_t &Loc, DIExpressionCursor &Cursor, SmallVectorImpl< uint64_t > &WorkingOps)
{DW_OP_constu, 0, DW_OP_[plus, minus, shl, shr]} -> {} {DW_OP_constu, 1, DW_OP_[mul,...
Definition DIExpressionOptimizer.cpp:193
static bool operationsAreFoldableAndCommutative(dwarf::LocationAtom Operator1, dwarf::LocationAtom Operator2)
Returns true if the two operations Operator1 and Operator2 are commutative and can be folded.
Definition DIExpressionOptimizer.cpp:91
static bool isNeutralElement(uint64_t Op, uint64_t Val)
Returns true if an operation and operand result in a No Op.
Definition DIExpressionOptimizer.cpp:27
static std::optional< uint64_t > foldOperationIfPossible(uint64_t Const1, uint64_t Const2, dwarf::LocationAtom Operator)
Try to fold Const1 and Const2 by applying Operator and returning the result, if there is an overflow,...
Definition DIExpressionOptimizer.cpp:45
static bool tryFoldCommutativeMath(uint64_t Const1, ArrayRef< DIExpression::ExprOperand > Ops, uint64_t &Loc, DIExpressionCursor &Cursor, SmallVectorImpl< uint64_t > &WorkingOps)
{DW_OP_constu, Const1, DW_OP_[plus, mul], DW_OP_constu, Const2, DW_OP_[plus, mul]}...
Definition DIExpressionOptimizer.cpp:234
void startFromBeginning(uint64_t &Loc, DIExpressionCursor &Cursor, ArrayRef< uint64_t > WorkingOps)
Reset the Cursor to the beginning of the WorkingOps.
Definition DIExpressionOptimizer.cpp:105
static SmallVector< uint64_t > optimizeDwarfOperations(ArrayRef< uint64_t > WorkingOps)
This function will convert:
Definition DIExpressionOptimizer.cpp:150
static bool tryFoldCommutativeMathWithArgInBetween(uint64_t Const1, ArrayRef< DIExpression::ExprOperand > Ops, uint64_t &Loc, DIExpressionCursor &Cursor, SmallVectorImpl< uint64_t > &WorkingOps)
{DW_OP_constu, Const1, DW_OP_[plus, mul], DW_OP_LLVM_arg, Arg1, DW_OP_[plus, mul],...
Definition DIExpressionOptimizer.cpp:262
static bool tryFoldConstants(uint64_t Const1, ArrayRef< DIExpression::ExprOperand > Ops, uint64_t &Loc, DIExpressionCursor &Cursor, SmallVectorImpl< uint64_t > &WorkingOps)
{DW_OP_constu, Const1, DW_OP_constu, Const2, DW_OP_[plus, minus, mul, div, shl, shr] -> {DW_OP_constu...
Definition DIExpressionOptimizer.cpp:209
static void consumeOneOperator(DIExpressionCursor &Cursor, uint64_t &Loc, const DIExpression::ExprOperand &Op)
Consume one operator and its operand(s).
Definition DIExpressionOptimizer.cpp:98
static std::optional< uint64_t > isConstantVal(DIExpression::ExprOperand Op)
Returns true if the Op is a DW_OP_constu.
Definition DIExpressionOptimizer.cpp:20
static SmallVector< uint64_t > canonicalizeDwarfOperations(ArrayRef< uint64_t > WorkingOps)
This function will canonicalize:
Definition DIExpressionOptimizer.cpp:115
This file contains constants used for implementing Dwarf debug support.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
Holds a DIExpression and keeps track of how many operands have been consumed so far.
A lightweight wrapper around an expression operand.
LLVM_ABI DIExpression * foldConstantMath()
Try to shorten an expression with constant math operations that can be evaluated at compile time.
Definition DIExpressionOptimizer.cpp:288
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
LLVMContext & getContext() const
This is a utility class that provides an abstraction for the common functionality between Instruction...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
iterator erase(const_iterator CI)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
@ DW_OP_LLVM_arg
Only used in LLVM metadata.
This is an optimization pass for GlobalISel generic memory operations.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
int countl_zero(T Val)
Count number of 0's from the most significant bit to the least stopping at the first 1.
std::enable_if_t< std::is_unsigned_v< T >, T > SaturatingMultiply(T X, T Y, bool *ResultOverflowed=nullptr)
Multiply two unsigned integers, X and Y, of type T.
DWARFExpression::Operation Op
std::enable_if_t< std::is_unsigned_v< T >, T > SaturatingAdd(T X, T Y, bool *ResultOverflowed=nullptr)
Add two unsigned integers, X and Y, of type T.