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