1249259Sdim//===-- llvm/Operator.h - Operator utility subclass -------------*- C++ -*-===//
2249259Sdim//
3249259Sdim//                     The LLVM Compiler Infrastructure
4249259Sdim//
5249259Sdim// This file is distributed under the University of Illinois Open Source
6249259Sdim// License. See LICENSE.TXT for details.
7249259Sdim//
8249259Sdim//===----------------------------------------------------------------------===//
9249259Sdim//
10249259Sdim// This file defines various classes for working with Instructions and
11249259Sdim// ConstantExprs.
12249259Sdim//
13249259Sdim//===----------------------------------------------------------------------===//
14249259Sdim
15249259Sdim#ifndef LLVM_IR_OPERATOR_H
16249259Sdim#define LLVM_IR_OPERATOR_H
17249259Sdim
18249259Sdim#include "llvm/IR/Constants.h"
19249259Sdim#include "llvm/IR/DataLayout.h"
20249259Sdim#include "llvm/IR/DerivedTypes.h"
21249259Sdim#include "llvm/IR/Instruction.h"
22249259Sdim#include "llvm/IR/Type.h"
23249259Sdim#include "llvm/Support/GetElementPtrTypeIterator.h"
24249259Sdim
25249259Sdimnamespace llvm {
26249259Sdim
27249259Sdimclass GetElementPtrInst;
28249259Sdimclass BinaryOperator;
29249259Sdimclass ConstantExpr;
30249259Sdim
31249259Sdim/// Operator - This is a utility class that provides an abstraction for the
32249259Sdim/// common functionality between Instructions and ConstantExprs.
33249259Sdim///
34249259Sdimclass Operator : public User {
35249259Sdimprivate:
36249259Sdim  // The Operator class is intended to be used as a utility, and is never itself
37249259Sdim  // instantiated.
38249259Sdim  void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION;
39249259Sdim  void *operator new(size_t s) LLVM_DELETED_FUNCTION;
40249259Sdim  Operator() LLVM_DELETED_FUNCTION;
41249259Sdim
42249259Sdimprotected:
43249259Sdim  // NOTE: Cannot use LLVM_DELETED_FUNCTION because it's not legal to delete
44249259Sdim  // an overridden method that's not deleted in the base class. Cannot leave
45249259Sdim  // this unimplemented because that leads to an ODR-violation.
46249259Sdim  ~Operator();
47249259Sdim
48249259Sdimpublic:
49249259Sdim  /// getOpcode - Return the opcode for this Instruction or ConstantExpr.
50249259Sdim  ///
51249259Sdim  unsigned getOpcode() const {
52249259Sdim    if (const Instruction *I = dyn_cast<Instruction>(this))
53249259Sdim      return I->getOpcode();
54249259Sdim    return cast<ConstantExpr>(this)->getOpcode();
55249259Sdim  }
56249259Sdim
57249259Sdim  /// getOpcode - If V is an Instruction or ConstantExpr, return its
58249259Sdim  /// opcode. Otherwise return UserOp1.
59249259Sdim  ///
60249259Sdim  static unsigned getOpcode(const Value *V) {
61249259Sdim    if (const Instruction *I = dyn_cast<Instruction>(V))
62249259Sdim      return I->getOpcode();
63249259Sdim    if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
64249259Sdim      return CE->getOpcode();
65249259Sdim    return Instruction::UserOp1;
66249259Sdim  }
67249259Sdim
68249259Sdim  static inline bool classof(const Instruction *) { return true; }
69249259Sdim  static inline bool classof(const ConstantExpr *) { return true; }
70249259Sdim  static inline bool classof(const Value *V) {
71249259Sdim    return isa<Instruction>(V) || isa<ConstantExpr>(V);
72249259Sdim  }
73249259Sdim};
74249259Sdim
75249259Sdim/// OverflowingBinaryOperator - Utility class for integer arithmetic operators
76249259Sdim/// which may exhibit overflow - Add, Sub, and Mul. It does not include SDiv,
77249259Sdim/// despite that operator having the potential for overflow.
78249259Sdim///
79249259Sdimclass OverflowingBinaryOperator : public Operator {
80249259Sdimpublic:
81249259Sdim  enum {
82249259Sdim    NoUnsignedWrap = (1 << 0),
83249259Sdim    NoSignedWrap   = (1 << 1)
84249259Sdim  };
85249259Sdim
86249259Sdimprivate:
87249259Sdim  friend class BinaryOperator;
88249259Sdim  friend class ConstantExpr;
89249259Sdim  void setHasNoUnsignedWrap(bool B) {
90249259Sdim    SubclassOptionalData =
91249259Sdim      (SubclassOptionalData & ~NoUnsignedWrap) | (B * NoUnsignedWrap);
92249259Sdim  }
93249259Sdim  void setHasNoSignedWrap(bool B) {
94249259Sdim    SubclassOptionalData =
95249259Sdim      (SubclassOptionalData & ~NoSignedWrap) | (B * NoSignedWrap);
96249259Sdim  }
97249259Sdim
98249259Sdimpublic:
99249259Sdim  /// hasNoUnsignedWrap - Test whether this operation is known to never
100249259Sdim  /// undergo unsigned overflow, aka the nuw property.
101249259Sdim  bool hasNoUnsignedWrap() const {
102249259Sdim    return SubclassOptionalData & NoUnsignedWrap;
103249259Sdim  }
104249259Sdim
105249259Sdim  /// hasNoSignedWrap - Test whether this operation is known to never
106249259Sdim  /// undergo signed overflow, aka the nsw property.
107249259Sdim  bool hasNoSignedWrap() const {
108249259Sdim    return (SubclassOptionalData & NoSignedWrap) != 0;
109249259Sdim  }
110249259Sdim
111249259Sdim  static inline bool classof(const Instruction *I) {
112249259Sdim    return I->getOpcode() == Instruction::Add ||
113249259Sdim           I->getOpcode() == Instruction::Sub ||
114249259Sdim           I->getOpcode() == Instruction::Mul ||
115249259Sdim           I->getOpcode() == Instruction::Shl;
116249259Sdim  }
117249259Sdim  static inline bool classof(const ConstantExpr *CE) {
118249259Sdim    return CE->getOpcode() == Instruction::Add ||
119249259Sdim           CE->getOpcode() == Instruction::Sub ||
120249259Sdim           CE->getOpcode() == Instruction::Mul ||
121249259Sdim           CE->getOpcode() == Instruction::Shl;
122249259Sdim  }
123249259Sdim  static inline bool classof(const Value *V) {
124249259Sdim    return (isa<Instruction>(V) && classof(cast<Instruction>(V))) ||
125249259Sdim           (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V)));
126249259Sdim  }
127249259Sdim};
128249259Sdim
129249259Sdim/// PossiblyExactOperator - A udiv or sdiv instruction, which can be marked as
130249259Sdim/// "exact", indicating that no bits are destroyed.
131249259Sdimclass PossiblyExactOperator : public Operator {
132249259Sdimpublic:
133249259Sdim  enum {
134249259Sdim    IsExact = (1 << 0)
135249259Sdim  };
136249259Sdim
137249259Sdimprivate:
138249259Sdim  friend class BinaryOperator;
139249259Sdim  friend class ConstantExpr;
140249259Sdim  void setIsExact(bool B) {
141249259Sdim    SubclassOptionalData = (SubclassOptionalData & ~IsExact) | (B * IsExact);
142249259Sdim  }
143249259Sdim
144249259Sdimpublic:
145249259Sdim  /// isExact - Test whether this division is known to be exact, with
146249259Sdim  /// zero remainder.
147249259Sdim  bool isExact() const {
148249259Sdim    return SubclassOptionalData & IsExact;
149249259Sdim  }
150249259Sdim
151249259Sdim  static bool isPossiblyExactOpcode(unsigned OpC) {
152249259Sdim    return OpC == Instruction::SDiv ||
153249259Sdim           OpC == Instruction::UDiv ||
154249259Sdim           OpC == Instruction::AShr ||
155249259Sdim           OpC == Instruction::LShr;
156249259Sdim  }
157249259Sdim  static inline bool classof(const ConstantExpr *CE) {
158249259Sdim    return isPossiblyExactOpcode(CE->getOpcode());
159249259Sdim  }
160249259Sdim  static inline bool classof(const Instruction *I) {
161249259Sdim    return isPossiblyExactOpcode(I->getOpcode());
162249259Sdim  }
163249259Sdim  static inline bool classof(const Value *V) {
164249259Sdim    return (isa<Instruction>(V) && classof(cast<Instruction>(V))) ||
165249259Sdim           (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V)));
166249259Sdim  }
167249259Sdim};
168249259Sdim
169249259Sdim/// Convenience struct for specifying and reasoning about fast-math flags.
170249259Sdimclass FastMathFlags {
171249259Sdimprivate:
172249259Sdim  friend class FPMathOperator;
173249259Sdim  unsigned Flags;
174249259Sdim  FastMathFlags(unsigned F) : Flags(F) { }
175249259Sdim
176249259Sdimpublic:
177249259Sdim  enum {
178249259Sdim    UnsafeAlgebra   = (1 << 0),
179249259Sdim    NoNaNs          = (1 << 1),
180249259Sdim    NoInfs          = (1 << 2),
181249259Sdim    NoSignedZeros   = (1 << 3),
182249259Sdim    AllowReciprocal = (1 << 4)
183249259Sdim  };
184249259Sdim
185249259Sdim  FastMathFlags() : Flags(0)
186249259Sdim  { }
187249259Sdim
188249259Sdim  /// Whether any flag is set
189249259Sdim  bool any() { return Flags != 0; }
190249259Sdim
191249259Sdim  /// Set all the flags to false
192249259Sdim  void clear() { Flags = 0; }
193249259Sdim
194249259Sdim  /// Flag queries
195249259Sdim  bool noNaNs()          { return 0 != (Flags & NoNaNs); }
196249259Sdim  bool noInfs()          { return 0 != (Flags & NoInfs); }
197249259Sdim  bool noSignedZeros()   { return 0 != (Flags & NoSignedZeros); }
198249259Sdim  bool allowReciprocal() { return 0 != (Flags & AllowReciprocal); }
199249259Sdim  bool unsafeAlgebra()   { return 0 != (Flags & UnsafeAlgebra); }
200249259Sdim
201249259Sdim  /// Flag setters
202249259Sdim  void setNoNaNs()          { Flags |= NoNaNs; }
203249259Sdim  void setNoInfs()          { Flags |= NoInfs; }
204249259Sdim  void setNoSignedZeros()   { Flags |= NoSignedZeros; }
205249259Sdim  void setAllowReciprocal() { Flags |= AllowReciprocal; }
206249259Sdim  void setUnsafeAlgebra() {
207249259Sdim    Flags |= UnsafeAlgebra;
208249259Sdim    setNoNaNs();
209249259Sdim    setNoInfs();
210249259Sdim    setNoSignedZeros();
211249259Sdim    setAllowReciprocal();
212249259Sdim  }
213249259Sdim};
214249259Sdim
215249259Sdim
216249259Sdim/// FPMathOperator - Utility class for floating point operations which can have
217249259Sdim/// information about relaxed accuracy requirements attached to them.
218249259Sdimclass FPMathOperator : public Operator {
219249259Sdimprivate:
220249259Sdim  friend class Instruction;
221249259Sdim
222249259Sdim  void setHasUnsafeAlgebra(bool B) {
223249259Sdim    SubclassOptionalData =
224249259Sdim      (SubclassOptionalData & ~FastMathFlags::UnsafeAlgebra) |
225249259Sdim      (B * FastMathFlags::UnsafeAlgebra);
226249259Sdim
227249259Sdim    // Unsafe algebra implies all the others
228249259Sdim    if (B) {
229249259Sdim      setHasNoNaNs(true);
230249259Sdim      setHasNoInfs(true);
231249259Sdim      setHasNoSignedZeros(true);
232249259Sdim      setHasAllowReciprocal(true);
233249259Sdim    }
234249259Sdim  }
235249259Sdim  void setHasNoNaNs(bool B) {
236249259Sdim    SubclassOptionalData =
237249259Sdim      (SubclassOptionalData & ~FastMathFlags::NoNaNs) |
238249259Sdim      (B * FastMathFlags::NoNaNs);
239249259Sdim  }
240249259Sdim  void setHasNoInfs(bool B) {
241249259Sdim    SubclassOptionalData =
242249259Sdim      (SubclassOptionalData & ~FastMathFlags::NoInfs) |
243249259Sdim      (B * FastMathFlags::NoInfs);
244249259Sdim  }
245249259Sdim  void setHasNoSignedZeros(bool B) {
246249259Sdim    SubclassOptionalData =
247249259Sdim      (SubclassOptionalData & ~FastMathFlags::NoSignedZeros) |
248249259Sdim      (B * FastMathFlags::NoSignedZeros);
249249259Sdim  }
250249259Sdim  void setHasAllowReciprocal(bool B) {
251249259Sdim    SubclassOptionalData =
252249259Sdim      (SubclassOptionalData & ~FastMathFlags::AllowReciprocal) |
253249259Sdim      (B * FastMathFlags::AllowReciprocal);
254249259Sdim  }
255249259Sdim
256249259Sdim  /// Convenience function for setting all the fast-math flags
257249259Sdim  void setFastMathFlags(FastMathFlags FMF) {
258249259Sdim    SubclassOptionalData |= FMF.Flags;
259249259Sdim  }
260249259Sdim
261249259Sdimpublic:
262249259Sdim  /// Test whether this operation is permitted to be
263249259Sdim  /// algebraically transformed, aka the 'A' fast-math property.
264249259Sdim  bool hasUnsafeAlgebra() const {
265249259Sdim    return (SubclassOptionalData & FastMathFlags::UnsafeAlgebra) != 0;
266249259Sdim  }
267249259Sdim
268249259Sdim  /// Test whether this operation's arguments and results are to be
269249259Sdim  /// treated as non-NaN, aka the 'N' fast-math property.
270249259Sdim  bool hasNoNaNs() const {
271249259Sdim    return (SubclassOptionalData & FastMathFlags::NoNaNs) != 0;
272249259Sdim  }
273249259Sdim
274249259Sdim  /// Test whether this operation's arguments and results are to be
275249259Sdim  /// treated as NoN-Inf, aka the 'I' fast-math property.
276249259Sdim  bool hasNoInfs() const {
277249259Sdim    return (SubclassOptionalData & FastMathFlags::NoInfs) != 0;
278249259Sdim  }
279249259Sdim
280249259Sdim  /// Test whether this operation can treat the sign of zero
281249259Sdim  /// as insignificant, aka the 'S' fast-math property.
282249259Sdim  bool hasNoSignedZeros() const {
283249259Sdim    return (SubclassOptionalData & FastMathFlags::NoSignedZeros) != 0;
284249259Sdim  }
285249259Sdim
286249259Sdim  /// Test whether this operation is permitted to use
287249259Sdim  /// reciprocal instead of division, aka the 'R' fast-math property.
288249259Sdim  bool hasAllowReciprocal() const {
289249259Sdim    return (SubclassOptionalData & FastMathFlags::AllowReciprocal) != 0;
290249259Sdim  }
291249259Sdim
292249259Sdim  /// Convenience function for getting all the fast-math flags
293249259Sdim  FastMathFlags getFastMathFlags() const {
294249259Sdim    return FastMathFlags(SubclassOptionalData);
295249259Sdim  }
296249259Sdim
297249259Sdim  /// \brief Get the maximum error permitted by this operation in ULPs.  An
298249259Sdim  /// accuracy of 0.0 means that the operation should be performed with the
299249259Sdim  /// default precision.
300249259Sdim  float getFPAccuracy() const;
301249259Sdim
302249259Sdim  static inline bool classof(const Instruction *I) {
303249259Sdim    return I->getType()->isFPOrFPVectorTy();
304249259Sdim  }
305249259Sdim  static inline bool classof(const Value *V) {
306249259Sdim    return isa<Instruction>(V) && classof(cast<Instruction>(V));
307249259Sdim  }
308249259Sdim};
309249259Sdim
310249259Sdim
311249259Sdim/// ConcreteOperator - A helper template for defining operators for individual
312249259Sdim/// opcodes.
313249259Sdimtemplate<typename SuperClass, unsigned Opc>
314249259Sdimclass ConcreteOperator : public SuperClass {
315249259Sdimpublic:
316249259Sdim  static inline bool classof(const Instruction *I) {
317249259Sdim    return I->getOpcode() == Opc;
318249259Sdim  }
319249259Sdim  static inline bool classof(const ConstantExpr *CE) {
320249259Sdim    return CE->getOpcode() == Opc;
321249259Sdim  }
322249259Sdim  static inline bool classof(const Value *V) {
323249259Sdim    return (isa<Instruction>(V) && classof(cast<Instruction>(V))) ||
324249259Sdim           (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V)));
325249259Sdim  }
326249259Sdim};
327249259Sdim
328249259Sdimclass AddOperator
329249259Sdim  : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Add> {
330249259Sdim};
331249259Sdimclass SubOperator
332249259Sdim  : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Sub> {
333249259Sdim};
334249259Sdimclass MulOperator
335249259Sdim  : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Mul> {
336249259Sdim};
337249259Sdimclass ShlOperator
338249259Sdim  : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Shl> {
339249259Sdim};
340249259Sdim
341249259Sdim
342249259Sdimclass SDivOperator
343249259Sdim  : public ConcreteOperator<PossiblyExactOperator, Instruction::SDiv> {
344249259Sdim};
345249259Sdimclass UDivOperator
346249259Sdim  : public ConcreteOperator<PossiblyExactOperator, Instruction::UDiv> {
347249259Sdim};
348249259Sdimclass AShrOperator
349249259Sdim  : public ConcreteOperator<PossiblyExactOperator, Instruction::AShr> {
350249259Sdim};
351249259Sdimclass LShrOperator
352249259Sdim  : public ConcreteOperator<PossiblyExactOperator, Instruction::LShr> {
353249259Sdim};
354249259Sdim
355249259Sdim
356249259Sdim
357249259Sdimclass GEPOperator
358249259Sdim  : public ConcreteOperator<Operator, Instruction::GetElementPtr> {
359249259Sdim  enum {
360249259Sdim    IsInBounds = (1 << 0)
361249259Sdim  };
362249259Sdim
363249259Sdim  friend class GetElementPtrInst;
364249259Sdim  friend class ConstantExpr;
365249259Sdim  void setIsInBounds(bool B) {
366249259Sdim    SubclassOptionalData =
367249259Sdim      (SubclassOptionalData & ~IsInBounds) | (B * IsInBounds);
368249259Sdim  }
369249259Sdim
370249259Sdimpublic:
371249259Sdim  /// isInBounds - Test whether this is an inbounds GEP, as defined
372249259Sdim  /// by LangRef.html.
373249259Sdim  bool isInBounds() const {
374249259Sdim    return SubclassOptionalData & IsInBounds;
375249259Sdim  }
376249259Sdim
377249259Sdim  inline op_iterator       idx_begin()       { return op_begin()+1; }
378249259Sdim  inline const_op_iterator idx_begin() const { return op_begin()+1; }
379249259Sdim  inline op_iterator       idx_end()         { return op_end(); }
380249259Sdim  inline const_op_iterator idx_end()   const { return op_end(); }
381249259Sdim
382249259Sdim  Value *getPointerOperand() {
383249259Sdim    return getOperand(0);
384249259Sdim  }
385249259Sdim  const Value *getPointerOperand() const {
386249259Sdim    return getOperand(0);
387249259Sdim  }
388249259Sdim  static unsigned getPointerOperandIndex() {
389249259Sdim    return 0U;                      // get index for modifying correct operand
390249259Sdim  }
391249259Sdim
392249259Sdim  /// getPointerOperandType - Method to return the pointer operand as a
393249259Sdim  /// PointerType.
394249259Sdim  Type *getPointerOperandType() const {
395249259Sdim    return getPointerOperand()->getType();
396249259Sdim  }
397249259Sdim
398249259Sdim  /// getPointerAddressSpace - Method to return the address space of the
399249259Sdim  /// pointer operand.
400249259Sdim  unsigned getPointerAddressSpace() const {
401249259Sdim    return cast<PointerType>(getPointerOperandType())->getAddressSpace();
402249259Sdim  }
403249259Sdim
404249259Sdim  unsigned getNumIndices() const {  // Note: always non-negative
405249259Sdim    return getNumOperands() - 1;
406249259Sdim  }
407249259Sdim
408249259Sdim  bool hasIndices() const {
409249259Sdim    return getNumOperands() > 1;
410249259Sdim  }
411249259Sdim
412249259Sdim  /// hasAllZeroIndices - Return true if all of the indices of this GEP are
413249259Sdim  /// zeros.  If so, the result pointer and the first operand have the same
414249259Sdim  /// value, just potentially different types.
415249259Sdim  bool hasAllZeroIndices() const {
416249259Sdim    for (const_op_iterator I = idx_begin(), E = idx_end(); I != E; ++I) {
417249259Sdim      if (ConstantInt *C = dyn_cast<ConstantInt>(I))
418249259Sdim        if (C->isZero())
419249259Sdim          continue;
420249259Sdim      return false;
421249259Sdim    }
422249259Sdim    return true;
423249259Sdim  }
424249259Sdim
425249259Sdim  /// hasAllConstantIndices - Return true if all of the indices of this GEP are
426249259Sdim  /// constant integers.  If so, the result pointer and the first operand have
427249259Sdim  /// a constant offset between them.
428249259Sdim  bool hasAllConstantIndices() const {
429249259Sdim    for (const_op_iterator I = idx_begin(), E = idx_end(); I != E; ++I) {
430249259Sdim      if (!isa<ConstantInt>(I))
431249259Sdim        return false;
432249259Sdim    }
433249259Sdim    return true;
434249259Sdim  }
435249259Sdim
436249259Sdim  /// \brief Accumulate the constant address offset of this GEP if possible.
437249259Sdim  ///
438249259Sdim  /// This routine accepts an APInt into which it will accumulate the constant
439249259Sdim  /// offset of this GEP if the GEP is in fact constant. If the GEP is not
440249259Sdim  /// all-constant, it returns false and the value of the offset APInt is
441249259Sdim  /// undefined (it is *not* preserved!). The APInt passed into this routine
442249259Sdim  /// must be at least as wide as the IntPtr type for the address space of
443249259Sdim  /// the base GEP pointer.
444249259Sdim  bool accumulateConstantOffset(const DataLayout &DL, APInt &Offset) const {
445249259Sdim    assert(Offset.getBitWidth() ==
446249259Sdim           DL.getPointerSizeInBits(getPointerAddressSpace()) &&
447249259Sdim           "The offset must have exactly as many bits as our pointer.");
448249259Sdim
449249259Sdim    for (gep_type_iterator GTI = gep_type_begin(this), GTE = gep_type_end(this);
450249259Sdim         GTI != GTE; ++GTI) {
451249259Sdim      ConstantInt *OpC = dyn_cast<ConstantInt>(GTI.getOperand());
452249259Sdim      if (!OpC)
453249259Sdim        return false;
454249259Sdim      if (OpC->isZero())
455249259Sdim        continue;
456249259Sdim
457249259Sdim      // Handle a struct index, which adds its field offset to the pointer.
458249259Sdim      if (StructType *STy = dyn_cast<StructType>(*GTI)) {
459249259Sdim        unsigned ElementIdx = OpC->getZExtValue();
460249259Sdim        const StructLayout *SL = DL.getStructLayout(STy);
461249259Sdim        Offset += APInt(Offset.getBitWidth(),
462249259Sdim                        SL->getElementOffset(ElementIdx));
463249259Sdim        continue;
464249259Sdim      }
465249259Sdim
466249259Sdim      // For array or vector indices, scale the index by the size of the type.
467249259Sdim      APInt Index = OpC->getValue().sextOrTrunc(Offset.getBitWidth());
468249259Sdim      Offset += Index * APInt(Offset.getBitWidth(),
469249259Sdim                              DL.getTypeAllocSize(GTI.getIndexedType()));
470249259Sdim    }
471249259Sdim    return true;
472249259Sdim  }
473249259Sdim
474249259Sdim};
475249259Sdim
476249259Sdim} // End llvm namespace
477249259Sdim
478249259Sdim#endif
479