diff options
Diffstat (limited to 'contrib/llvm/lib/IR/Instruction.cpp')
-rw-r--r-- | contrib/llvm/lib/IR/Instruction.cpp | 188 |
1 files changed, 115 insertions, 73 deletions
diff --git a/contrib/llvm/lib/IR/Instruction.cpp b/contrib/llvm/lib/IR/Instruction.cpp index 2fa0348..365cb01 100644 --- a/contrib/llvm/lib/IR/Instruction.cpp +++ b/contrib/llvm/lib/IR/Instruction.cpp @@ -11,11 +11,12 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ADT/DenseSet.h" #include "llvm/IR/Instruction.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/IR/CallSite.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Instructions.h" +#include "llvm/IR/MDBuilder.h" #include "llvm/IR/Module.h" #include "llvm/IR/Operator.h" #include "llvm/IR/Type.h" @@ -42,8 +43,6 @@ Instruction::Instruction(Type *ty, unsigned it, Use *Ops, unsigned NumOps, InsertAtEnd->getInstList().push_back(this); } - -// Out of line virtual method, so the vtable, etc has a home. Instruction::~Instruction() { assert(!Parent && "Instruction still linked in the program!"); if (hasMetadataHashEntry()) @@ -59,12 +58,6 @@ const Module *Instruction::getModule() const { return getParent()->getModule(); } -Module *Instruction::getModule() { - return getParent()->getModule(); -} - -Function *Instruction::getFunction() { return getParent()->getParent(); } - const Function *Instruction::getFunction() const { return getParent()->getParent(); } @@ -122,6 +115,29 @@ bool Instruction::hasNoSignedWrap() const { return cast<OverflowingBinaryOperator>(this)->hasNoSignedWrap(); } +void Instruction::dropPoisonGeneratingFlags() { + switch (getOpcode()) { + case Instruction::Add: + case Instruction::Sub: + case Instruction::Mul: + case Instruction::Shl: + cast<OverflowingBinaryOperator>(this)->setHasNoUnsignedWrap(false); + cast<OverflowingBinaryOperator>(this)->setHasNoSignedWrap(false); + break; + + case Instruction::UDiv: + case Instruction::SDiv: + case Instruction::AShr: + case Instruction::LShr: + cast<PossiblyExactOperator>(this)->setIsExact(false); + break; + + case Instruction::GetElementPtr: + cast<GetElementPtrInst>(this)->setIsInBounds(false); + break; + } +} + bool Instruction::isExact() const { return cast<PossiblyExactOperator>(this)->isExact(); } @@ -186,6 +202,11 @@ bool Instruction::hasAllowReciprocal() const { return cast<FPMathOperator>(this)->hasAllowReciprocal(); } +bool Instruction::hasAllowContract() const { + assert(isa<FPMathOperator>(this) && "getting fast-math flag on invalid op"); + return cast<FPMathOperator>(this)->hasAllowContract(); +} + FastMathFlags Instruction::getFastMathFlags() const { assert(isa<FPMathOperator>(this) && "getting fast-math flag on invalid op"); return cast<FPMathOperator>(this)->getFastMathFlags(); @@ -195,10 +216,10 @@ void Instruction::copyFastMathFlags(const Instruction *I) { copyFastMathFlags(I->getFastMathFlags()); } -void Instruction::copyIRFlags(const Value *V) { +void Instruction::copyIRFlags(const Value *V, bool IncludeWrapFlags) { // Copy the wrapping flags. - if (auto *OB = dyn_cast<OverflowingBinaryOperator>(V)) { - if (isa<OverflowingBinaryOperator>(this)) { + if (IncludeWrapFlags && isa<OverflowingBinaryOperator>(this)) { + if (auto *OB = dyn_cast<OverflowingBinaryOperator>(V)) { setHasNoSignedWrap(OB->hasNoSignedWrap()); setHasNoUnsignedWrap(OB->hasNoUnsignedWrap()); } @@ -341,13 +362,13 @@ static bool haveSameSpecialState(const Instruction *I1, const Instruction *I2, (LI->getAlignment() == cast<LoadInst>(I2)->getAlignment() || IgnoreAlignment) && LI->getOrdering() == cast<LoadInst>(I2)->getOrdering() && - LI->getSynchScope() == cast<LoadInst>(I2)->getSynchScope(); + LI->getSyncScopeID() == cast<LoadInst>(I2)->getSyncScopeID(); if (const StoreInst *SI = dyn_cast<StoreInst>(I1)) return SI->isVolatile() == cast<StoreInst>(I2)->isVolatile() && (SI->getAlignment() == cast<StoreInst>(I2)->getAlignment() || IgnoreAlignment) && SI->getOrdering() == cast<StoreInst>(I2)->getOrdering() && - SI->getSynchScope() == cast<StoreInst>(I2)->getSynchScope(); + SI->getSyncScopeID() == cast<StoreInst>(I2)->getSyncScopeID(); if (const CmpInst *CI = dyn_cast<CmpInst>(I1)) return CI->getPredicate() == cast<CmpInst>(I2)->getPredicate(); if (const CallInst *CI = dyn_cast<CallInst>(I1)) @@ -365,7 +386,7 @@ static bool haveSameSpecialState(const Instruction *I1, const Instruction *I2, return EVI->getIndices() == cast<ExtractValueInst>(I2)->getIndices(); if (const FenceInst *FI = dyn_cast<FenceInst>(I1)) return FI->getOrdering() == cast<FenceInst>(I2)->getOrdering() && - FI->getSynchScope() == cast<FenceInst>(I2)->getSynchScope(); + FI->getSyncScopeID() == cast<FenceInst>(I2)->getSyncScopeID(); if (const AtomicCmpXchgInst *CXI = dyn_cast<AtomicCmpXchgInst>(I1)) return CXI->isVolatile() == cast<AtomicCmpXchgInst>(I2)->isVolatile() && CXI->isWeak() == cast<AtomicCmpXchgInst>(I2)->isWeak() && @@ -373,12 +394,13 @@ static bool haveSameSpecialState(const Instruction *I1, const Instruction *I2, cast<AtomicCmpXchgInst>(I2)->getSuccessOrdering() && CXI->getFailureOrdering() == cast<AtomicCmpXchgInst>(I2)->getFailureOrdering() && - CXI->getSynchScope() == cast<AtomicCmpXchgInst>(I2)->getSynchScope(); + CXI->getSyncScopeID() == + cast<AtomicCmpXchgInst>(I2)->getSyncScopeID(); if (const AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(I1)) return RMWI->getOperation() == cast<AtomicRMWInst>(I2)->getOperation() && RMWI->isVolatile() == cast<AtomicRMWInst>(I2)->isVolatile() && RMWI->getOrdering() == cast<AtomicRMWInst>(I2)->getOrdering() && - RMWI->getSynchScope() == cast<AtomicRMWInst>(I2)->getSynchScope(); + RMWI->getSyncScopeID() == cast<AtomicRMWInst>(I2)->getSyncScopeID(); return true; } @@ -511,6 +533,30 @@ bool Instruction::isAtomic() const { } } +bool Instruction::hasAtomicLoad() const { + assert(isAtomic()); + switch (getOpcode()) { + default: + return false; + case Instruction::AtomicCmpXchg: + case Instruction::AtomicRMW: + case Instruction::Load: + return true; + } +} + +bool Instruction::hasAtomicStore() const { + assert(isAtomic()); + switch (getOpcode()) { + default: + return false; + case Instruction::AtomicCmpXchg: + case Instruction::AtomicRMW: + case Instruction::Store: + return true; + } +} + bool Instruction::mayThrow() const { if (const CallInst *CI = dyn_cast<CallInst>(this)) return !CI->doesNotThrow(); @@ -521,17 +567,6 @@ bool Instruction::mayThrow() const { return isa<ResumeInst>(this); } -/// Return true if the instruction is associative: -/// -/// Associative operators satisfy: x op (y op z) === (x op y) op z -/// -/// In LLVM, the Add, Mul, And, Or, and Xor operators are associative. -/// -bool Instruction::isAssociative(unsigned Opcode) { - return Opcode == And || Opcode == Or || Opcode == Xor || - Opcode == Add || Opcode == Mul; -} - bool Instruction::isAssociative() const { unsigned Opcode = getOpcode(); if (isAssociative(Opcode)) @@ -546,51 +581,6 @@ bool Instruction::isAssociative() const { } } -/// Return true if the instruction is commutative: -/// -/// Commutative operators satisfy: (x op y) === (y op x) -/// -/// In LLVM, these are the associative operators, plus SetEQ and SetNE, when -/// applied to any type. -/// -bool Instruction::isCommutative(unsigned op) { - switch (op) { - case Add: - case FAdd: - case Mul: - case FMul: - case And: - case Or: - case Xor: - return true; - default: - return false; - } -} - -/// Return true if the instruction is idempotent: -/// -/// Idempotent operators satisfy: x op x === x -/// -/// In LLVM, the And and Or operators are idempotent. -/// -bool Instruction::isIdempotent(unsigned Opcode) { - return Opcode == And || Opcode == Or; -} - -/// Return true if the instruction is nilpotent: -/// -/// Nilpotent operators satisfy: x op x === Id, -/// -/// where Id is the identity for the operator, i.e. a constant such that -/// x op Id === x and Id op x === x for all x. -/// -/// In LLVM, the Xor operator is nilpotent. -/// -bool Instruction::isNilpotent(unsigned Opcode) { - return Opcode == Xor; -} - Instruction *Instruction::cloneImpl() const { llvm_unreachable("Subclass of Instruction failed to implement cloneImpl"); } @@ -651,3 +641,55 @@ Instruction *Instruction::clone() const { New->copyMetadata(*this); return New; } + +void Instruction::updateProfWeight(uint64_t S, uint64_t T) { + auto *ProfileData = getMetadata(LLVMContext::MD_prof); + if (ProfileData == nullptr) + return; + + auto *ProfDataName = dyn_cast<MDString>(ProfileData->getOperand(0)); + if (!ProfDataName || (!ProfDataName->getString().equals("branch_weights") && + !ProfDataName->getString().equals("VP"))) + return; + + MDBuilder MDB(getContext()); + SmallVector<Metadata *, 3> Vals; + Vals.push_back(ProfileData->getOperand(0)); + APInt APS(128, S), APT(128, T); + if (ProfDataName->getString().equals("branch_weights")) + for (unsigned i = 1; i < ProfileData->getNumOperands(); i++) { + // Using APInt::div may be expensive, but most cases should fit 64 bits. + APInt Val(128, + mdconst::dyn_extract<ConstantInt>(ProfileData->getOperand(i)) + ->getValue() + .getZExtValue()); + Val *= APS; + Vals.push_back(MDB.createConstant( + ConstantInt::get(Type::getInt64Ty(getContext()), + Val.udiv(APT).getLimitedValue()))); + } + else if (ProfDataName->getString().equals("VP")) + for (unsigned i = 1; i < ProfileData->getNumOperands(); i += 2) { + // The first value is the key of the value profile, which will not change. + Vals.push_back(ProfileData->getOperand(i)); + // Using APInt::div may be expensive, but most cases should fit 64 bits. + APInt Val(128, + mdconst::dyn_extract<ConstantInt>(ProfileData->getOperand(i + 1)) + ->getValue() + .getZExtValue()); + Val *= APS; + Vals.push_back(MDB.createConstant( + ConstantInt::get(Type::getInt64Ty(getContext()), + Val.udiv(APT).getLimitedValue()))); + } + setMetadata(LLVMContext::MD_prof, MDNode::get(getContext(), Vals)); +} + +void Instruction::setProfWeight(uint64_t W) { + assert((isa<CallInst>(this) || isa<InvokeInst>(this)) && + "Can only set weights for call and invoke instrucitons"); + SmallVector<uint32_t, 1> Weights; + Weights.push_back(W); + MDBuilder MDB(getContext()); + setMetadata(LLVMContext::MD_prof, MDB.createBranchWeights(Weights)); +} |