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