1 | //===-- llvm/Operator.h - Operator utility subclass -------------*- C++ -*-===// |
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 | // This file defines various classes for working with Instructions and |
10 | // ConstantExprs. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #ifndef LLVM_IR_OPERATOR_H |
15 | #define LLVM_IR_OPERATOR_H |
16 | |
17 | #include "llvm/ADT/MapVector.h" |
18 | #include "llvm/ADT/None.h" |
19 | #include "llvm/ADT/Optional.h" |
20 | #include "llvm/IR/Constants.h" |
21 | #include "llvm/IR/Instruction.h" |
22 | #include "llvm/IR/Type.h" |
23 | #include "llvm/IR/Value.h" |
24 | #include "llvm/Support/Casting.h" |
25 | #include <cstddef> |
26 | |
27 | namespace llvm { |
28 | |
29 | /// This is a utility class that provides an abstraction for the common |
30 | /// functionality between Instructions and ConstantExprs. |
31 | class Operator : public User { |
32 | public: |
33 | // The Operator class is intended to be used as a utility, and is never itself |
34 | // instantiated. |
35 | Operator() = delete; |
36 | ~Operator() = delete; |
37 | |
38 | void *operator new(size_t s) = delete; |
39 | |
40 | /// Return the opcode for this Instruction or ConstantExpr. |
41 | unsigned getOpcode() const { |
42 | if (const Instruction *I = dyn_cast<Instruction>(this)) |
43 | return I->getOpcode(); |
44 | return cast<ConstantExpr>(this)->getOpcode(); |
45 | } |
46 | |
47 | /// If V is an Instruction or ConstantExpr, return its opcode. |
48 | /// Otherwise return UserOp1. |
49 | static unsigned getOpcode(const Value *V) { |
50 | if (const Instruction *I = dyn_cast<Instruction>(V)) |
51 | return I->getOpcode(); |
52 | if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) |
53 | return CE->getOpcode(); |
54 | return Instruction::UserOp1; |
55 | } |
56 | |
57 | static bool classof(const Instruction *) { return true; } |
58 | static bool classof(const ConstantExpr *) { return true; } |
59 | static bool classof(const Value *V) { |
60 | return isa<Instruction>(V) || isa<ConstantExpr>(V); |
61 | } |
62 | |
63 | /// Return true if this operator has flags which may cause this operator |
64 | /// to evaluate to poison despite having non-poison inputs. |
65 | bool hasPoisonGeneratingFlags() const; |
66 | }; |
67 | |
68 | /// Utility class for integer operators which may exhibit overflow - Add, Sub, |
69 | /// Mul, and Shl. It does not include SDiv, despite that operator having the |
70 | /// potential for overflow. |
71 | class OverflowingBinaryOperator : public Operator { |
72 | public: |
73 | enum { |
74 | AnyWrap = 0, |
75 | NoUnsignedWrap = (1 << 0), |
76 | NoSignedWrap = (1 << 1) |
77 | }; |
78 | |
79 | private: |
80 | friend class Instruction; |
81 | friend class ConstantExpr; |
82 | |
83 | void setHasNoUnsignedWrap(bool B) { |
84 | SubclassOptionalData = |
85 | (SubclassOptionalData & ~NoUnsignedWrap) | (B * NoUnsignedWrap); |
86 | } |
87 | void setHasNoSignedWrap(bool B) { |
88 | SubclassOptionalData = |
89 | (SubclassOptionalData & ~NoSignedWrap) | (B * NoSignedWrap); |
90 | } |
91 | |
92 | public: |
93 | /// Test whether this operation is known to never |
94 | /// undergo unsigned overflow, aka the nuw property. |
95 | bool hasNoUnsignedWrap() const { |
96 | return SubclassOptionalData & NoUnsignedWrap; |
97 | } |
98 | |
99 | /// Test whether this operation is known to never |
100 | /// undergo signed overflow, aka the nsw property. |
101 | bool hasNoSignedWrap() const { |
102 | return (SubclassOptionalData & NoSignedWrap) != 0; |
103 | } |
104 | |
105 | static bool classof(const Instruction *I) { |
106 | return I->getOpcode() == Instruction::Add || |
107 | I->getOpcode() == Instruction::Sub || |
108 | I->getOpcode() == Instruction::Mul || |
109 | I->getOpcode() == Instruction::Shl; |
110 | } |
111 | static bool classof(const ConstantExpr *CE) { |
112 | return CE->getOpcode() == Instruction::Add || |
113 | CE->getOpcode() == Instruction::Sub || |
114 | CE->getOpcode() == Instruction::Mul || |
115 | CE->getOpcode() == Instruction::Shl; |
116 | } |
117 | static bool classof(const Value *V) { |
118 | return (isa<Instruction>(V) && classof(cast<Instruction>(V))) || |
119 | (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V))); |
120 | } |
121 | }; |
122 | |
123 | /// A udiv or sdiv instruction, which can be marked as "exact", |
124 | /// indicating that no bits are destroyed. |
125 | class PossiblyExactOperator : public Operator { |
126 | public: |
127 | enum { |
128 | IsExact = (1 << 0) |
129 | }; |
130 | |
131 | private: |
132 | friend class Instruction; |
133 | friend class ConstantExpr; |
134 | |
135 | void setIsExact(bool B) { |
136 | SubclassOptionalData = (SubclassOptionalData & ~IsExact) | (B * IsExact); |
137 | } |
138 | |
139 | public: |
140 | /// Test whether this division is known to be exact, with zero remainder. |
141 | bool isExact() const { |
142 | return SubclassOptionalData & IsExact; |
143 | } |
144 | |
145 | static bool isPossiblyExactOpcode(unsigned OpC) { |
146 | return OpC == Instruction::SDiv || |
147 | OpC == Instruction::UDiv || |
148 | OpC == Instruction::AShr || |
149 | OpC == Instruction::LShr; |
150 | } |
151 | |
152 | static bool classof(const ConstantExpr *CE) { |
153 | return isPossiblyExactOpcode(CE->getOpcode()); |
154 | } |
155 | static bool classof(const Instruction *I) { |
156 | return isPossiblyExactOpcode(I->getOpcode()); |
157 | } |
158 | static bool classof(const Value *V) { |
159 | return (isa<Instruction>(V) && classof(cast<Instruction>(V))) || |
160 | (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V))); |
161 | } |
162 | }; |
163 | |
164 | /// Convenience struct for specifying and reasoning about fast-math flags. |
165 | class FastMathFlags { |
166 | private: |
167 | friend class FPMathOperator; |
168 | |
169 | unsigned Flags = 0; |
170 | |
171 | FastMathFlags(unsigned F) { |
172 | // If all 7 bits are set, turn this into -1. If the number of bits grows, |
173 | // this must be updated. This is intended to provide some forward binary |
174 | // compatibility insurance for the meaning of 'fast' in case bits are added. |
175 | if (F == 0x7F) Flags = ~0U; |
176 | else Flags = F; |
177 | } |
178 | |
179 | public: |
180 | // This is how the bits are used in Value::SubclassOptionalData so they |
181 | // should fit there too. |
182 | // WARNING: We're out of space. SubclassOptionalData only has 7 bits. New |
183 | // functionality will require a change in how this information is stored. |
184 | enum { |
185 | AllowReassoc = (1 << 0), |
186 | NoNaNs = (1 << 1), |
187 | NoInfs = (1 << 2), |
188 | NoSignedZeros = (1 << 3), |
189 | AllowReciprocal = (1 << 4), |
190 | AllowContract = (1 << 5), |
191 | ApproxFunc = (1 << 6) |
192 | }; |
193 | |
194 | FastMathFlags() = default; |
195 | |
196 | static FastMathFlags getFast() { |
197 | FastMathFlags FMF; |
198 | FMF.setFast(); |
199 | return FMF; |
200 | } |
201 | |
202 | bool any() const { return Flags != 0; } |
203 | bool none() const { return Flags == 0; } |
204 | bool all() const { return Flags == ~0U; } |
205 | |
206 | void clear() { Flags = 0; } |
207 | void set() { Flags = ~0U; } |
208 | |
209 | /// Flag queries |
210 | bool allowReassoc() const { return 0 != (Flags & AllowReassoc); } |
211 | bool noNaNs() const { return 0 != (Flags & NoNaNs); } |
212 | bool noInfs() const { return 0 != (Flags & NoInfs); } |
213 | bool noSignedZeros() const { return 0 != (Flags & NoSignedZeros); } |
214 | bool allowReciprocal() const { return 0 != (Flags & AllowReciprocal); } |
215 | bool allowContract() const { return 0 != (Flags & AllowContract); } |
216 | bool approxFunc() const { return 0 != (Flags & ApproxFunc); } |
217 | /// 'Fast' means all bits are set. |
218 | bool isFast() const { return all(); } |
219 | |
220 | /// Flag setters |
221 | void setAllowReassoc(bool B = true) { |
222 | Flags = (Flags & ~AllowReassoc) | B * AllowReassoc; |
223 | } |
224 | void setNoNaNs(bool B = true) { |
225 | Flags = (Flags & ~NoNaNs) | B * NoNaNs; |
226 | } |
227 | void setNoInfs(bool B = true) { |
228 | Flags = (Flags & ~NoInfs) | B * NoInfs; |
229 | } |
230 | void setNoSignedZeros(bool B = true) { |
231 | Flags = (Flags & ~NoSignedZeros) | B * NoSignedZeros; |
232 | } |
233 | void setAllowReciprocal(bool B = true) { |
234 | Flags = (Flags & ~AllowReciprocal) | B * AllowReciprocal; |
235 | } |
236 | void setAllowContract(bool B = true) { |
237 | Flags = (Flags & ~AllowContract) | B * AllowContract; |
238 | } |
239 | void setApproxFunc(bool B = true) { |
240 | Flags = (Flags & ~ApproxFunc) | B * ApproxFunc; |
241 | } |
242 | void setFast(bool B = true) { B ? set() : clear(); } |
243 | |
244 | void operator&=(const FastMathFlags &OtherFlags) { |
245 | Flags &= OtherFlags.Flags; |
246 | } |
247 | void operator|=(const FastMathFlags &OtherFlags) { |
248 | Flags |= OtherFlags.Flags; |
249 | } |
250 | bool operator!=(const FastMathFlags &OtherFlags) const { |
251 | return Flags != OtherFlags.Flags; |
252 | } |
253 | |
254 | /// Print fast-math flags to \p O. |
255 | void print(raw_ostream &O) const; |
256 | }; |
257 | |
258 | inline raw_ostream &operator<<(raw_ostream &O, FastMathFlags FMF) { |
259 | FMF.print(O); |
260 | return O; |
261 | } |
262 | |
263 | /// Utility class for floating point operations which can have |
264 | /// information about relaxed accuracy requirements attached to them. |
265 | class FPMathOperator : public Operator { |
266 | private: |
267 | friend class Instruction; |
268 | |
269 | /// 'Fast' means all bits are set. |
270 | void setFast(bool B) { |
271 | setHasAllowReassoc(B); |
272 | setHasNoNaNs(B); |
273 | setHasNoInfs(B); |
274 | setHasNoSignedZeros(B); |
275 | setHasAllowReciprocal(B); |
276 | setHasAllowContract(B); |
277 | setHasApproxFunc(B); |
278 | } |
279 | |
280 | void setHasAllowReassoc(bool B) { |
281 | SubclassOptionalData = |
282 | (SubclassOptionalData & ~FastMathFlags::AllowReassoc) | |
283 | (B * FastMathFlags::AllowReassoc); |
284 | } |
285 | |
286 | void setHasNoNaNs(bool B) { |
287 | SubclassOptionalData = |
288 | (SubclassOptionalData & ~FastMathFlags::NoNaNs) | |
289 | (B * FastMathFlags::NoNaNs); |
290 | } |
291 | |
292 | void setHasNoInfs(bool B) { |
293 | SubclassOptionalData = |
294 | (SubclassOptionalData & ~FastMathFlags::NoInfs) | |
295 | (B * FastMathFlags::NoInfs); |
296 | } |
297 | |
298 | void setHasNoSignedZeros(bool B) { |
299 | SubclassOptionalData = |
300 | (SubclassOptionalData & ~FastMathFlags::NoSignedZeros) | |
301 | (B * FastMathFlags::NoSignedZeros); |
302 | } |
303 | |
304 | void setHasAllowReciprocal(bool B) { |
305 | SubclassOptionalData = |
306 | (SubclassOptionalData & ~FastMathFlags::AllowReciprocal) | |
307 | (B * FastMathFlags::AllowReciprocal); |
308 | } |
309 | |
310 | void setHasAllowContract(bool B) { |
311 | SubclassOptionalData = |
312 | (SubclassOptionalData & ~FastMathFlags::AllowContract) | |
313 | (B * FastMathFlags::AllowContract); |
314 | } |
315 | |
316 | void setHasApproxFunc(bool B) { |
317 | SubclassOptionalData = |
318 | (SubclassOptionalData & ~FastMathFlags::ApproxFunc) | |
319 | (B * FastMathFlags::ApproxFunc); |
320 | } |
321 | |
322 | /// Convenience function for setting multiple fast-math flags. |
323 | /// FMF is a mask of the bits to set. |
324 | void setFastMathFlags(FastMathFlags FMF) { |
325 | SubclassOptionalData |= FMF.Flags; |
326 | } |
327 | |
328 | /// Convenience function for copying all fast-math flags. |
329 | /// All values in FMF are transferred to this operator. |
330 | void copyFastMathFlags(FastMathFlags FMF) { |
331 | SubclassOptionalData = FMF.Flags; |
332 | } |
333 | |
334 | public: |
335 | /// Test if this operation allows all non-strict floating-point transforms. |
336 | bool isFast() const { |
337 | return ((SubclassOptionalData & FastMathFlags::AllowReassoc) != 0 && |
338 | (SubclassOptionalData & FastMathFlags::NoNaNs) != 0 && |
339 | (SubclassOptionalData & FastMathFlags::NoInfs) != 0 && |
340 | (SubclassOptionalData & FastMathFlags::NoSignedZeros) != 0 && |
341 | (SubclassOptionalData & FastMathFlags::AllowReciprocal) != 0 && |
342 | (SubclassOptionalData & FastMathFlags::AllowContract) != 0 && |
343 | (SubclassOptionalData & FastMathFlags::ApproxFunc) != 0); |
344 | } |
345 | |
346 | /// Test if this operation may be simplified with reassociative transforms. |
347 | bool hasAllowReassoc() const { |
348 | return (SubclassOptionalData & FastMathFlags::AllowReassoc) != 0; |
349 | } |
350 | |
351 | /// Test if this operation's arguments and results are assumed not-NaN. |
352 | bool hasNoNaNs() const { |
353 | return (SubclassOptionalData & FastMathFlags::NoNaNs) != 0; |
354 | } |
355 | |
356 | /// Test if this operation's arguments and results are assumed not-infinite. |
357 | bool hasNoInfs() const { |
358 | return (SubclassOptionalData & FastMathFlags::NoInfs) != 0; |
359 | } |
360 | |
361 | /// Test if this operation can ignore the sign of zero. |
362 | bool hasNoSignedZeros() const { |
363 | return (SubclassOptionalData & FastMathFlags::NoSignedZeros) != 0; |
364 | } |
365 | |
366 | /// Test if this operation can use reciprocal multiply instead of division. |
367 | bool hasAllowReciprocal() const { |
368 | return (SubclassOptionalData & FastMathFlags::AllowReciprocal) != 0; |
369 | } |
370 | |
371 | /// Test if this operation can be floating-point contracted (FMA). |
372 | bool hasAllowContract() const { |
373 | return (SubclassOptionalData & FastMathFlags::AllowContract) != 0; |
374 | } |
375 | |
376 | /// Test if this operation allows approximations of math library functions or |
377 | /// intrinsics. |
378 | bool hasApproxFunc() const { |
379 | return (SubclassOptionalData & FastMathFlags::ApproxFunc) != 0; |
380 | } |
381 | |
382 | /// Convenience function for getting all the fast-math flags |
383 | FastMathFlags getFastMathFlags() const { |
384 | return FastMathFlags(SubclassOptionalData); |
385 | } |
386 | |
387 | /// Get the maximum error permitted by this operation in ULPs. An accuracy of |
388 | /// 0.0 means that the operation should be performed with the default |
389 | /// precision. |
390 | float getFPAccuracy() const; |
391 | |
392 | static bool classof(const Value *V) { |
393 | unsigned Opcode; |
394 | if (auto *I = dyn_cast<Instruction>(V)) |
395 | Opcode = I->getOpcode(); |
396 | else if (auto *CE = dyn_cast<ConstantExpr>(V)) |
397 | Opcode = CE->getOpcode(); |
398 | else |
399 | return false; |
400 | |
401 | switch (Opcode) { |
402 | case Instruction::FNeg: |
403 | case Instruction::FAdd: |
404 | case Instruction::FSub: |
405 | case Instruction::FMul: |
406 | case Instruction::FDiv: |
407 | case Instruction::FRem: |
408 | // FIXME: To clean up and correct the semantics of fast-math-flags, FCmp |
409 | // should not be treated as a math op, but the other opcodes should. |
410 | // This would make things consistent with Select/PHI (FP value type |
411 | // determines whether they are math ops and, therefore, capable of |
412 | // having fast-math-flags). |
413 | case Instruction::FCmp: |
414 | return true; |
415 | case Instruction::PHI: |
416 | case Instruction::Select: |
417 | case Instruction::Call: { |
418 | Type *Ty = V->getType(); |
419 | while (ArrayType *ArrTy = dyn_cast<ArrayType>(Ty)) |
420 | Ty = ArrTy->getElementType(); |
421 | return Ty->isFPOrFPVectorTy(); |
422 | } |
423 | default: |
424 | return false; |
425 | } |
426 | } |
427 | }; |
428 | |
429 | /// A helper template for defining operators for individual opcodes. |
430 | template<typename SuperClass, unsigned Opc> |
431 | class ConcreteOperator : public SuperClass { |
432 | public: |
433 | static bool classof(const Instruction *I) { |
434 | return I->getOpcode() == Opc; |
435 | } |
436 | static bool classof(const ConstantExpr *CE) { |
437 | return CE->getOpcode() == Opc; |
438 | } |
439 | static bool classof(const Value *V) { |
440 | return (isa<Instruction>(V) && classof(cast<Instruction>(V))) || |
441 | (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V))); |
442 | } |
443 | }; |
444 | |
445 | class AddOperator |
446 | : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Add> { |
447 | }; |
448 | class SubOperator |
449 | : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Sub> { |
450 | }; |
451 | class MulOperator |
452 | : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Mul> { |
453 | }; |
454 | class ShlOperator |
455 | : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Shl> { |
456 | }; |
457 | |
458 | class SDivOperator |
459 | : public ConcreteOperator<PossiblyExactOperator, Instruction::SDiv> { |
460 | }; |
461 | class UDivOperator |
462 | : public ConcreteOperator<PossiblyExactOperator, Instruction::UDiv> { |
463 | }; |
464 | class AShrOperator |
465 | : public ConcreteOperator<PossiblyExactOperator, Instruction::AShr> { |
466 | }; |
467 | class LShrOperator |
468 | : public ConcreteOperator<PossiblyExactOperator, Instruction::LShr> { |
469 | }; |
470 | |
471 | class ZExtOperator : public ConcreteOperator<Operator, Instruction::ZExt> {}; |
472 | |
473 | class GEPOperator |
474 | : public ConcreteOperator<Operator, Instruction::GetElementPtr> { |
475 | friend class GetElementPtrInst; |
476 | friend class ConstantExpr; |
477 | |
478 | enum { |
479 | IsInBounds = (1 << 0), |
480 | // InRangeIndex: bits 1-6 |
481 | }; |
482 | |
483 | void setIsInBounds(bool B) { |
484 | SubclassOptionalData = |
485 | (SubclassOptionalData & ~IsInBounds) | (B * IsInBounds); |
486 | } |
487 | |
488 | public: |
489 | /// Test whether this is an inbounds GEP, as defined by LangRef.html. |
490 | bool isInBounds() const { |
491 | return SubclassOptionalData & IsInBounds; |
492 | } |
493 | |
494 | /// Returns the offset of the index with an inrange attachment, or None if |
495 | /// none. |
496 | Optional<unsigned> getInRangeIndex() const { |
497 | if (SubclassOptionalData >> 1 == 0) return None; |
498 | return (SubclassOptionalData >> 1) - 1; |
499 | } |
500 | |
501 | inline op_iterator idx_begin() { return op_begin()+1; } |
502 | inline const_op_iterator idx_begin() const { return op_begin()+1; } |
503 | inline op_iterator idx_end() { return op_end(); } |
504 | inline const_op_iterator idx_end() const { return op_end(); } |
505 | |
506 | inline iterator_range<op_iterator> indices() { |
507 | return make_range(idx_begin(), idx_end()); |
508 | } |
509 | |
510 | inline iterator_range<const_op_iterator> indices() const { |
511 | return make_range(idx_begin(), idx_end()); |
512 | } |
513 | |
514 | Value *getPointerOperand() { |
515 | return getOperand(0); |
516 | } |
517 | const Value *getPointerOperand() const { |
518 | return getOperand(0); |
519 | } |
520 | static unsigned getPointerOperandIndex() { |
521 | return 0U; // get index for modifying correct operand |
522 | } |
523 | |
524 | /// Method to return the pointer operand as a PointerType. |
525 | Type *getPointerOperandType() const { |
526 | return getPointerOperand()->getType(); |
527 | } |
528 | |
529 | Type *getSourceElementType() const; |
530 | Type *getResultElementType() const; |
531 | |
532 | /// Method to return the address space of the pointer operand. |
533 | unsigned getPointerAddressSpace() const { |
534 | return getPointerOperandType()->getPointerAddressSpace(); |
535 | } |
536 | |
537 | unsigned getNumIndices() const { // Note: always non-negative |
538 | return getNumOperands() - 1; |
539 | } |
540 | |
541 | bool hasIndices() const { |
542 | return getNumOperands() > 1; |
543 | } |
544 | |
545 | /// Return true if all of the indices of this GEP are zeros. |
546 | /// If so, the result pointer and the first operand have the same |
547 | /// value, just potentially different types. |
548 | bool hasAllZeroIndices() const { |
549 | for (const_op_iterator I = idx_begin(), E = idx_end(); I != E; ++I) { |
550 | if (ConstantInt *C = dyn_cast<ConstantInt>(I)) |
551 | if (C->isZero()) |
552 | continue; |
553 | return false; |
554 | } |
555 | return true; |
556 | } |
557 | |
558 | /// Return true if all of the indices of this GEP are constant integers. |
559 | /// If so, the result pointer and the first operand have |
560 | /// a constant offset between them. |
561 | bool hasAllConstantIndices() const { |
562 | for (const_op_iterator I = idx_begin(), E = idx_end(); I != E; ++I) { |
563 | if (!isa<ConstantInt>(I)) |
564 | return false; |
565 | } |
566 | return true; |
567 | } |
568 | |
569 | unsigned countNonConstantIndices() const { |
570 | return count_if(indices(), [](const Use& use) { |
571 | return !isa<ConstantInt>(*use); |
572 | }); |
573 | } |
574 | |
575 | /// Compute the maximum alignment that this GEP is garranteed to preserve. |
576 | Align getMaxPreservedAlignment(const DataLayout &DL) const; |
577 | |
578 | /// Accumulate the constant address offset of this GEP if possible. |
579 | /// |
580 | /// This routine accepts an APInt into which it will try to accumulate the |
581 | /// constant offset of this GEP. |
582 | /// |
583 | /// If \p ExternalAnalysis is provided it will be used to calculate a offset |
584 | /// when a operand of GEP is not constant. |
585 | /// For example, for a value \p ExternalAnalysis might try to calculate a |
586 | /// lower bound. If \p ExternalAnalysis is successful, it should return true. |
587 | /// |
588 | /// If the \p ExternalAnalysis returns false or the value returned by \p |
589 | /// ExternalAnalysis results in a overflow/underflow, this routine returns |
590 | /// false and the value of the offset APInt is undefined (it is *not* |
591 | /// preserved!). |
592 | /// |
593 | /// The APInt passed into this routine must be at exactly as wide as the |
594 | /// IntPtr type for the address space of the base GEP pointer. |
595 | bool accumulateConstantOffset( |
596 | const DataLayout &DL, APInt &Offset, |
597 | function_ref<bool(Value &, APInt &)> ExternalAnalysis = nullptr) const; |
598 | |
599 | static bool accumulateConstantOffset( |
600 | Type *SourceType, ArrayRef<const Value *> Index, const DataLayout &DL, |
601 | APInt &Offset, |
602 | function_ref<bool(Value &, APInt &)> ExternalAnalysis = nullptr); |
603 | |
604 | /// Collect the offset of this GEP as a map of Values to their associated |
605 | /// APInt multipliers, as well as a total Constant Offset. |
606 | bool collectOffset(const DataLayout &DL, unsigned BitWidth, |
607 | MapVector<Value *, APInt> &VariableOffsets, |
608 | APInt &ConstantOffset) const; |
609 | }; |
610 | |
611 | class PtrToIntOperator |
612 | : public ConcreteOperator<Operator, Instruction::PtrToInt> { |
613 | friend class PtrToInt; |
614 | friend class ConstantExpr; |
615 | |
616 | public: |
617 | Value *getPointerOperand() { |
618 | return getOperand(0); |
619 | } |
620 | const Value *getPointerOperand() const { |
621 | return getOperand(0); |
622 | } |
623 | |
624 | static unsigned getPointerOperandIndex() { |
625 | return 0U; // get index for modifying correct operand |
626 | } |
627 | |
628 | /// Method to return the pointer operand as a PointerType. |
629 | Type *getPointerOperandType() const { |
630 | return getPointerOperand()->getType(); |
631 | } |
632 | |
633 | /// Method to return the address space of the pointer operand. |
634 | unsigned getPointerAddressSpace() const { |
635 | return cast<PointerType>(getPointerOperandType())->getAddressSpace(); |
636 | } |
637 | }; |
638 | |
639 | class BitCastOperator |
640 | : public ConcreteOperator<Operator, Instruction::BitCast> { |
641 | friend class BitCastInst; |
642 | friend class ConstantExpr; |
643 | |
644 | public: |
645 | Type *getSrcTy() const { |
646 | return getOperand(0)->getType(); |
647 | } |
648 | |
649 | Type *getDestTy() const { |
650 | return getType(); |
651 | } |
652 | }; |
653 | |
654 | class AddrSpaceCastOperator |
655 | : public ConcreteOperator<Operator, Instruction::AddrSpaceCast> { |
656 | friend class AddrSpaceCastInst; |
657 | friend class ConstantExpr; |
658 | |
659 | public: |
660 | Value *getPointerOperand() { return getOperand(0); } |
661 | |
662 | const Value *getPointerOperand() const { return getOperand(0); } |
663 | |
664 | unsigned getSrcAddressSpace() const { |
665 | return getPointerOperand()->getType()->getPointerAddressSpace(); |
666 | } |
667 | |
668 | unsigned getDestAddressSpace() const { |
669 | return getType()->getPointerAddressSpace(); |
670 | } |
671 | }; |
672 | |
673 | } // end namespace llvm |
674 | |
675 | #endif // LLVM_IR_OPERATOR_H |
676 | |