123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592 |
- #pragma once
- #ifdef __GNUC__
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wunused-parameter"
- #endif
- //===-- llvm/Operator.h - Operator utility subclass -------------*- C++ -*-===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- //
- // This file defines various classes for working with Instructions and
- // ConstantExprs.
- //
- //===----------------------------------------------------------------------===//
- #ifndef LLVM_IR_OPERATOR_H
- #define LLVM_IR_OPERATOR_H
- #include "llvm/ADT/MapVector.h"
- #include "llvm/IR/Constants.h"
- #include "llvm/IR/FMF.h"
- #include "llvm/IR/Instruction.h"
- #include "llvm/IR/Type.h"
- #include "llvm/IR/Value.h"
- #include "llvm/Support/Casting.h"
- #include <cstddef>
- #include <optional>
- namespace llvm {
- /// This is a utility class that provides an abstraction for the common
- /// functionality between Instructions and ConstantExprs.
- class Operator : public User {
- public:
- // The Operator class is intended to be used as a utility, and is never itself
- // instantiated.
- Operator() = delete;
- ~Operator() = delete;
- void *operator new(size_t s) = delete;
- /// Return the opcode for this Instruction or ConstantExpr.
- unsigned getOpcode() const {
- if (const Instruction *I = dyn_cast<Instruction>(this))
- return I->getOpcode();
- return cast<ConstantExpr>(this)->getOpcode();
- }
- /// If V is an Instruction or ConstantExpr, return its opcode.
- /// Otherwise return UserOp1.
- static unsigned getOpcode(const Value *V) {
- if (const Instruction *I = dyn_cast<Instruction>(V))
- return I->getOpcode();
- if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
- return CE->getOpcode();
- return Instruction::UserOp1;
- }
- static bool classof(const Instruction *) { return true; }
- static bool classof(const ConstantExpr *) { return true; }
- static bool classof(const Value *V) {
- return isa<Instruction>(V) || isa<ConstantExpr>(V);
- }
- /// Return true if this operator has flags which may cause this operator
- /// to evaluate to poison despite having non-poison inputs.
- bool hasPoisonGeneratingFlags() const;
- /// Return true if this operator has poison-generating flags or metadata.
- /// The latter is only possible for instructions.
- bool hasPoisonGeneratingFlagsOrMetadata() const;
- };
- /// Utility class for integer operators which may exhibit overflow - Add, Sub,
- /// Mul, and Shl. It does not include SDiv, despite that operator having the
- /// potential for overflow.
- class OverflowingBinaryOperator : public Operator {
- public:
- enum {
- AnyWrap = 0,
- NoUnsignedWrap = (1 << 0),
- NoSignedWrap = (1 << 1)
- };
- private:
- friend class Instruction;
- friend class ConstantExpr;
- void setHasNoUnsignedWrap(bool B) {
- SubclassOptionalData =
- (SubclassOptionalData & ~NoUnsignedWrap) | (B * NoUnsignedWrap);
- }
- void setHasNoSignedWrap(bool B) {
- SubclassOptionalData =
- (SubclassOptionalData & ~NoSignedWrap) | (B * NoSignedWrap);
- }
- public:
- /// Test whether this operation is known to never
- /// undergo unsigned overflow, aka the nuw property.
- bool hasNoUnsignedWrap() const {
- return SubclassOptionalData & NoUnsignedWrap;
- }
- /// Test whether this operation is known to never
- /// undergo signed overflow, aka the nsw property.
- bool hasNoSignedWrap() const {
- return (SubclassOptionalData & NoSignedWrap) != 0;
- }
- static bool classof(const Instruction *I) {
- return I->getOpcode() == Instruction::Add ||
- I->getOpcode() == Instruction::Sub ||
- I->getOpcode() == Instruction::Mul ||
- I->getOpcode() == Instruction::Shl;
- }
- static bool classof(const ConstantExpr *CE) {
- return CE->getOpcode() == Instruction::Add ||
- CE->getOpcode() == Instruction::Sub ||
- CE->getOpcode() == Instruction::Mul ||
- CE->getOpcode() == Instruction::Shl;
- }
- static bool classof(const Value *V) {
- return (isa<Instruction>(V) && classof(cast<Instruction>(V))) ||
- (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V)));
- }
- };
- /// A udiv or sdiv instruction, which can be marked as "exact",
- /// indicating that no bits are destroyed.
- class PossiblyExactOperator : public Operator {
- public:
- enum {
- IsExact = (1 << 0)
- };
- private:
- friend class Instruction;
- friend class ConstantExpr;
- void setIsExact(bool B) {
- SubclassOptionalData = (SubclassOptionalData & ~IsExact) | (B * IsExact);
- }
- public:
- /// Test whether this division is known to be exact, with zero remainder.
- bool isExact() const {
- return SubclassOptionalData & IsExact;
- }
- static bool isPossiblyExactOpcode(unsigned OpC) {
- return OpC == Instruction::SDiv ||
- OpC == Instruction::UDiv ||
- OpC == Instruction::AShr ||
- OpC == Instruction::LShr;
- }
- static bool classof(const ConstantExpr *CE) {
- return isPossiblyExactOpcode(CE->getOpcode());
- }
- static bool classof(const Instruction *I) {
- return isPossiblyExactOpcode(I->getOpcode());
- }
- static bool classof(const Value *V) {
- return (isa<Instruction>(V) && classof(cast<Instruction>(V))) ||
- (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V)));
- }
- };
- /// Utility class for floating point operations which can have
- /// information about relaxed accuracy requirements attached to them.
- class FPMathOperator : public Operator {
- private:
- friend class Instruction;
- /// 'Fast' means all bits are set.
- void setFast(bool B) {
- setHasAllowReassoc(B);
- setHasNoNaNs(B);
- setHasNoInfs(B);
- setHasNoSignedZeros(B);
- setHasAllowReciprocal(B);
- setHasAllowContract(B);
- setHasApproxFunc(B);
- }
- void setHasAllowReassoc(bool B) {
- SubclassOptionalData =
- (SubclassOptionalData & ~FastMathFlags::AllowReassoc) |
- (B * FastMathFlags::AllowReassoc);
- }
- void setHasNoNaNs(bool B) {
- SubclassOptionalData =
- (SubclassOptionalData & ~FastMathFlags::NoNaNs) |
- (B * FastMathFlags::NoNaNs);
- }
- void setHasNoInfs(bool B) {
- SubclassOptionalData =
- (SubclassOptionalData & ~FastMathFlags::NoInfs) |
- (B * FastMathFlags::NoInfs);
- }
- void setHasNoSignedZeros(bool B) {
- SubclassOptionalData =
- (SubclassOptionalData & ~FastMathFlags::NoSignedZeros) |
- (B * FastMathFlags::NoSignedZeros);
- }
- void setHasAllowReciprocal(bool B) {
- SubclassOptionalData =
- (SubclassOptionalData & ~FastMathFlags::AllowReciprocal) |
- (B * FastMathFlags::AllowReciprocal);
- }
- void setHasAllowContract(bool B) {
- SubclassOptionalData =
- (SubclassOptionalData & ~FastMathFlags::AllowContract) |
- (B * FastMathFlags::AllowContract);
- }
- void setHasApproxFunc(bool B) {
- SubclassOptionalData =
- (SubclassOptionalData & ~FastMathFlags::ApproxFunc) |
- (B * FastMathFlags::ApproxFunc);
- }
- /// Convenience function for setting multiple fast-math flags.
- /// FMF is a mask of the bits to set.
- void setFastMathFlags(FastMathFlags FMF) {
- SubclassOptionalData |= FMF.Flags;
- }
- /// Convenience function for copying all fast-math flags.
- /// All values in FMF are transferred to this operator.
- void copyFastMathFlags(FastMathFlags FMF) {
- SubclassOptionalData = FMF.Flags;
- }
- public:
- /// Test if this operation allows all non-strict floating-point transforms.
- bool isFast() const {
- return ((SubclassOptionalData & FastMathFlags::AllowReassoc) != 0 &&
- (SubclassOptionalData & FastMathFlags::NoNaNs) != 0 &&
- (SubclassOptionalData & FastMathFlags::NoInfs) != 0 &&
- (SubclassOptionalData & FastMathFlags::NoSignedZeros) != 0 &&
- (SubclassOptionalData & FastMathFlags::AllowReciprocal) != 0 &&
- (SubclassOptionalData & FastMathFlags::AllowContract) != 0 &&
- (SubclassOptionalData & FastMathFlags::ApproxFunc) != 0);
- }
- /// Test if this operation may be simplified with reassociative transforms.
- bool hasAllowReassoc() const {
- return (SubclassOptionalData & FastMathFlags::AllowReassoc) != 0;
- }
- /// Test if this operation's arguments and results are assumed not-NaN.
- bool hasNoNaNs() const {
- return (SubclassOptionalData & FastMathFlags::NoNaNs) != 0;
- }
- /// Test if this operation's arguments and results are assumed not-infinite.
- bool hasNoInfs() const {
- return (SubclassOptionalData & FastMathFlags::NoInfs) != 0;
- }
- /// Test if this operation can ignore the sign of zero.
- bool hasNoSignedZeros() const {
- return (SubclassOptionalData & FastMathFlags::NoSignedZeros) != 0;
- }
- /// Test if this operation can use reciprocal multiply instead of division.
- bool hasAllowReciprocal() const {
- return (SubclassOptionalData & FastMathFlags::AllowReciprocal) != 0;
- }
- /// Test if this operation can be floating-point contracted (FMA).
- bool hasAllowContract() const {
- return (SubclassOptionalData & FastMathFlags::AllowContract) != 0;
- }
- /// Test if this operation allows approximations of math library functions or
- /// intrinsics.
- bool hasApproxFunc() const {
- return (SubclassOptionalData & FastMathFlags::ApproxFunc) != 0;
- }
- /// Convenience function for getting all the fast-math flags
- FastMathFlags getFastMathFlags() const {
- return FastMathFlags(SubclassOptionalData);
- }
- /// Get the maximum error permitted by this operation in ULPs. An accuracy of
- /// 0.0 means that the operation should be performed with the default
- /// precision.
- float getFPAccuracy() const;
- static bool classof(const Value *V) {
- unsigned Opcode;
- if (auto *I = dyn_cast<Instruction>(V))
- Opcode = I->getOpcode();
- else if (auto *CE = dyn_cast<ConstantExpr>(V))
- Opcode = CE->getOpcode();
- else
- return false;
- switch (Opcode) {
- case Instruction::FNeg:
- case Instruction::FAdd:
- case Instruction::FSub:
- case Instruction::FMul:
- case Instruction::FDiv:
- case Instruction::FRem:
- // FIXME: To clean up and correct the semantics of fast-math-flags, FCmp
- // should not be treated as a math op, but the other opcodes should.
- // This would make things consistent with Select/PHI (FP value type
- // determines whether they are math ops and, therefore, capable of
- // having fast-math-flags).
- case Instruction::FCmp:
- return true;
- case Instruction::PHI:
- case Instruction::Select:
- case Instruction::Call: {
- Type *Ty = V->getType();
- while (ArrayType *ArrTy = dyn_cast<ArrayType>(Ty))
- Ty = ArrTy->getElementType();
- return Ty->isFPOrFPVectorTy();
- }
- default:
- return false;
- }
- }
- };
- /// A helper template for defining operators for individual opcodes.
- template<typename SuperClass, unsigned Opc>
- class ConcreteOperator : public SuperClass {
- public:
- static bool classof(const Instruction *I) {
- return I->getOpcode() == Opc;
- }
- static bool classof(const ConstantExpr *CE) {
- return CE->getOpcode() == Opc;
- }
- static bool classof(const Value *V) {
- return (isa<Instruction>(V) && classof(cast<Instruction>(V))) ||
- (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V)));
- }
- };
- class AddOperator
- : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Add> {
- };
- class SubOperator
- : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Sub> {
- };
- class MulOperator
- : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Mul> {
- };
- class ShlOperator
- : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Shl> {
- };
- class SDivOperator
- : public ConcreteOperator<PossiblyExactOperator, Instruction::SDiv> {
- };
- class UDivOperator
- : public ConcreteOperator<PossiblyExactOperator, Instruction::UDiv> {
- };
- class AShrOperator
- : public ConcreteOperator<PossiblyExactOperator, Instruction::AShr> {
- };
- class LShrOperator
- : public ConcreteOperator<PossiblyExactOperator, Instruction::LShr> {
- };
- class ZExtOperator : public ConcreteOperator<Operator, Instruction::ZExt> {};
- class GEPOperator
- : public ConcreteOperator<Operator, Instruction::GetElementPtr> {
- friend class GetElementPtrInst;
- friend class ConstantExpr;
- enum {
- IsInBounds = (1 << 0),
- // InRangeIndex: bits 1-6
- };
- void setIsInBounds(bool B) {
- SubclassOptionalData =
- (SubclassOptionalData & ~IsInBounds) | (B * IsInBounds);
- }
- public:
- /// Test whether this is an inbounds GEP, as defined by LangRef.html.
- bool isInBounds() const {
- return SubclassOptionalData & IsInBounds;
- }
- /// Returns the offset of the index with an inrange attachment, or
- /// std::nullopt if none.
- std::optional<unsigned> getInRangeIndex() const {
- if (SubclassOptionalData >> 1 == 0)
- return std::nullopt;
- return (SubclassOptionalData >> 1) - 1;
- }
- inline op_iterator idx_begin() { return op_begin()+1; }
- inline const_op_iterator idx_begin() const { return op_begin()+1; }
- inline op_iterator idx_end() { return op_end(); }
- inline const_op_iterator idx_end() const { return op_end(); }
- inline iterator_range<op_iterator> indices() {
- return make_range(idx_begin(), idx_end());
- }
- inline iterator_range<const_op_iterator> indices() const {
- return make_range(idx_begin(), idx_end());
- }
- Value *getPointerOperand() {
- return getOperand(0);
- }
- const Value *getPointerOperand() const {
- return getOperand(0);
- }
- static unsigned getPointerOperandIndex() {
- return 0U; // get index for modifying correct operand
- }
- /// Method to return the pointer operand as a PointerType.
- Type *getPointerOperandType() const {
- return getPointerOperand()->getType();
- }
- Type *getSourceElementType() const;
- Type *getResultElementType() const;
- /// Method to return the address space of the pointer operand.
- unsigned getPointerAddressSpace() const {
- return getPointerOperandType()->getPointerAddressSpace();
- }
- unsigned getNumIndices() const { // Note: always non-negative
- return getNumOperands() - 1;
- }
- bool hasIndices() const {
- return getNumOperands() > 1;
- }
- /// Return true if all of the indices of this GEP are zeros.
- /// If so, the result pointer and the first operand have the same
- /// value, just potentially different types.
- bool hasAllZeroIndices() const {
- for (const_op_iterator I = idx_begin(), E = idx_end(); I != E; ++I) {
- if (ConstantInt *C = dyn_cast<ConstantInt>(I))
- if (C->isZero())
- continue;
- return false;
- }
- return true;
- }
- /// Return true if all of the indices of this GEP are constant integers.
- /// If so, the result pointer and the first operand have
- /// a constant offset between them.
- bool hasAllConstantIndices() const {
- for (const_op_iterator I = idx_begin(), E = idx_end(); I != E; ++I) {
- if (!isa<ConstantInt>(I))
- return false;
- }
- return true;
- }
- unsigned countNonConstantIndices() const {
- return count_if(indices(), [](const Use& use) {
- return !isa<ConstantInt>(*use);
- });
- }
- /// Compute the maximum alignment that this GEP is garranteed to preserve.
- Align getMaxPreservedAlignment(const DataLayout &DL) const;
- /// Accumulate the constant address offset of this GEP if possible.
- ///
- /// This routine accepts an APInt into which it will try to accumulate the
- /// constant offset of this GEP.
- ///
- /// If \p ExternalAnalysis is provided it will be used to calculate a offset
- /// when a operand of GEP is not constant.
- /// For example, for a value \p ExternalAnalysis might try to calculate a
- /// lower bound. If \p ExternalAnalysis is successful, it should return true.
- ///
- /// If the \p ExternalAnalysis returns false or the value returned by \p
- /// ExternalAnalysis results in a overflow/underflow, this routine returns
- /// false and the value of the offset APInt is undefined (it is *not*
- /// preserved!).
- ///
- /// The APInt passed into this routine must be at exactly as wide as the
- /// IntPtr type for the address space of the base GEP pointer.
- bool accumulateConstantOffset(
- const DataLayout &DL, APInt &Offset,
- function_ref<bool(Value &, APInt &)> ExternalAnalysis = nullptr) const;
- static bool accumulateConstantOffset(
- Type *SourceType, ArrayRef<const Value *> Index, const DataLayout &DL,
- APInt &Offset,
- function_ref<bool(Value &, APInt &)> ExternalAnalysis = nullptr);
- /// Collect the offset of this GEP as a map of Values to their associated
- /// APInt multipliers, as well as a total Constant Offset.
- bool collectOffset(const DataLayout &DL, unsigned BitWidth,
- MapVector<Value *, APInt> &VariableOffsets,
- APInt &ConstantOffset) const;
- };
- class PtrToIntOperator
- : public ConcreteOperator<Operator, Instruction::PtrToInt> {
- friend class PtrToInt;
- friend class ConstantExpr;
- public:
- Value *getPointerOperand() {
- return getOperand(0);
- }
- const Value *getPointerOperand() const {
- return getOperand(0);
- }
- static unsigned getPointerOperandIndex() {
- return 0U; // get index for modifying correct operand
- }
- /// Method to return the pointer operand as a PointerType.
- Type *getPointerOperandType() const {
- return getPointerOperand()->getType();
- }
- /// Method to return the address space of the pointer operand.
- unsigned getPointerAddressSpace() const {
- return cast<PointerType>(getPointerOperandType())->getAddressSpace();
- }
- };
- class BitCastOperator
- : public ConcreteOperator<Operator, Instruction::BitCast> {
- friend class BitCastInst;
- friend class ConstantExpr;
- public:
- Type *getSrcTy() const {
- return getOperand(0)->getType();
- }
- Type *getDestTy() const {
- return getType();
- }
- };
- class AddrSpaceCastOperator
- : public ConcreteOperator<Operator, Instruction::AddrSpaceCast> {
- friend class AddrSpaceCastInst;
- friend class ConstantExpr;
- public:
- Value *getPointerOperand() { return getOperand(0); }
- const Value *getPointerOperand() const { return getOperand(0); }
- unsigned getSrcAddressSpace() const {
- return getPointerOperand()->getType()->getPointerAddressSpace();
- }
- unsigned getDestAddressSpace() const {
- return getType()->getPointerAddressSpace();
- }
- };
- } // end namespace llvm
- #endif // LLVM_IR_OPERATOR_H
- #ifdef __GNUC__
- #pragma GCC diagnostic pop
- #endif
|