Mercurial > hg > CbC > CbC_llvm
diff lib/IR/Instruction.cpp @ 120:1172e4bd9c6f
update 4.0.0
author | mir3636 |
---|---|
date | Fri, 25 Nov 2016 19:14:25 +0900 |
parents | 7d135dc70f03 |
children | 803732b1fca8 |
line wrap: on
line diff
--- a/lib/IR/Instruction.cpp Tue Jan 26 22:56:36 2016 +0900 +++ b/lib/IR/Instruction.cpp Fri Nov 25 19:14:25 2016 +0900 @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#include "llvm/ADT/DenseSet.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/CallSite.h" #include "llvm/IR/Constants.h" @@ -92,51 +93,64 @@ /// Unlink this instruction from its current basic block and insert it into the /// basic block that MovePos lives in, right before MovePos. void Instruction::moveBefore(Instruction *MovePos) { - MovePos->getParent()->getInstList().splice( - MovePos->getIterator(), getParent()->getInstList(), getIterator()); + moveBefore(*MovePos->getParent(), MovePos->getIterator()); +} + +void Instruction::moveBefore(BasicBlock &BB, + SymbolTableList<Instruction>::iterator I) { + assert(I == BB.end() || I->getParent() == &BB); + BB.getInstList().splice(I, getParent()->getInstList(), getIterator()); +} + +void Instruction::setHasNoUnsignedWrap(bool b) { + cast<OverflowingBinaryOperator>(this)->setHasNoUnsignedWrap(b); +} + +void Instruction::setHasNoSignedWrap(bool b) { + cast<OverflowingBinaryOperator>(this)->setHasNoSignedWrap(b); } -/// Set or clear the unsafe-algebra flag on this instruction, which must be an -/// operator which supports this flag. See LangRef.html for the meaning of this -/// flag. +void Instruction::setIsExact(bool b) { + cast<PossiblyExactOperator>(this)->setIsExact(b); +} + +bool Instruction::hasNoUnsignedWrap() const { + return cast<OverflowingBinaryOperator>(this)->hasNoUnsignedWrap(); +} + +bool Instruction::hasNoSignedWrap() const { + return cast<OverflowingBinaryOperator>(this)->hasNoSignedWrap(); +} + +bool Instruction::isExact() const { + return cast<PossiblyExactOperator>(this)->isExact(); +} + void Instruction::setHasUnsafeAlgebra(bool B) { assert(isa<FPMathOperator>(this) && "setting fast-math flag on invalid op"); cast<FPMathOperator>(this)->setHasUnsafeAlgebra(B); } -/// Set or clear the NoNaNs flag on this instruction, which must be an operator -/// which supports this flag. See LangRef.html for the meaning of this flag. void Instruction::setHasNoNaNs(bool B) { assert(isa<FPMathOperator>(this) && "setting fast-math flag on invalid op"); cast<FPMathOperator>(this)->setHasNoNaNs(B); } -/// Set or clear the no-infs flag on this instruction, which must be an operator -/// which supports this flag. See LangRef.html for the meaning of this flag. void Instruction::setHasNoInfs(bool B) { assert(isa<FPMathOperator>(this) && "setting fast-math flag on invalid op"); cast<FPMathOperator>(this)->setHasNoInfs(B); } -/// Set or clear the no-signed-zeros flag on this instruction, which must be an -/// operator which supports this flag. See LangRef.html for the meaning of this -/// flag. void Instruction::setHasNoSignedZeros(bool B) { assert(isa<FPMathOperator>(this) && "setting fast-math flag on invalid op"); cast<FPMathOperator>(this)->setHasNoSignedZeros(B); } -/// Set or clear the allow-reciprocal flag on this instruction, which must be an -/// operator which supports this flag. See LangRef.html for the meaning of this -/// flag. void Instruction::setHasAllowReciprocal(bool B) { assert(isa<FPMathOperator>(this) && "setting fast-math flag on invalid op"); cast<FPMathOperator>(this)->setHasAllowReciprocal(B); } -/// Convenience function for setting all the fast-math flags on this -/// instruction, which must be an operator which supports these flags. See -/// LangRef.html for the meaning of these flats. void Instruction::setFastMathFlags(FastMathFlags FMF) { assert(isa<FPMathOperator>(this) && "setting fast-math flag on invalid op"); cast<FPMathOperator>(this)->setFastMathFlags(FMF); @@ -147,49 +161,88 @@ cast<FPMathOperator>(this)->copyFastMathFlags(FMF); } -/// Determine whether the unsafe-algebra flag is set. bool Instruction::hasUnsafeAlgebra() const { assert(isa<FPMathOperator>(this) && "getting fast-math flag on invalid op"); return cast<FPMathOperator>(this)->hasUnsafeAlgebra(); } -/// Determine whether the no-NaNs flag is set. bool Instruction::hasNoNaNs() const { assert(isa<FPMathOperator>(this) && "getting fast-math flag on invalid op"); return cast<FPMathOperator>(this)->hasNoNaNs(); } -/// Determine whether the no-infs flag is set. bool Instruction::hasNoInfs() const { assert(isa<FPMathOperator>(this) && "getting fast-math flag on invalid op"); return cast<FPMathOperator>(this)->hasNoInfs(); } -/// Determine whether the no-signed-zeros flag is set. bool Instruction::hasNoSignedZeros() const { assert(isa<FPMathOperator>(this) && "getting fast-math flag on invalid op"); return cast<FPMathOperator>(this)->hasNoSignedZeros(); } -/// Determine whether the allow-reciprocal flag is set. bool Instruction::hasAllowReciprocal() const { assert(isa<FPMathOperator>(this) && "getting fast-math flag on invalid op"); return cast<FPMathOperator>(this)->hasAllowReciprocal(); } -/// Convenience function for getting all the fast-math flags, which must be an -/// operator which supports these flags. See LangRef.html for the meaning of -/// these flags. FastMathFlags Instruction::getFastMathFlags() const { assert(isa<FPMathOperator>(this) && "getting fast-math flag on invalid op"); return cast<FPMathOperator>(this)->getFastMathFlags(); } -/// Copy I's fast-math flags void Instruction::copyFastMathFlags(const Instruction *I) { copyFastMathFlags(I->getFastMathFlags()); } +void Instruction::copyIRFlags(const Value *V) { + // Copy the wrapping flags. + if (auto *OB = dyn_cast<OverflowingBinaryOperator>(V)) { + if (isa<OverflowingBinaryOperator>(this)) { + setHasNoSignedWrap(OB->hasNoSignedWrap()); + setHasNoUnsignedWrap(OB->hasNoUnsignedWrap()); + } + } + + // Copy the exact flag. + if (auto *PE = dyn_cast<PossiblyExactOperator>(V)) + if (isa<PossiblyExactOperator>(this)) + setIsExact(PE->isExact()); + + // Copy the fast-math flags. + if (auto *FP = dyn_cast<FPMathOperator>(V)) + if (isa<FPMathOperator>(this)) + copyFastMathFlags(FP->getFastMathFlags()); + + if (auto *SrcGEP = dyn_cast<GetElementPtrInst>(V)) + if (auto *DestGEP = dyn_cast<GetElementPtrInst>(this)) + DestGEP->setIsInBounds(SrcGEP->isInBounds() | DestGEP->isInBounds()); +} + +void Instruction::andIRFlags(const Value *V) { + if (auto *OB = dyn_cast<OverflowingBinaryOperator>(V)) { + if (isa<OverflowingBinaryOperator>(this)) { + setHasNoSignedWrap(hasNoSignedWrap() & OB->hasNoSignedWrap()); + setHasNoUnsignedWrap(hasNoUnsignedWrap() & OB->hasNoUnsignedWrap()); + } + } + + if (auto *PE = dyn_cast<PossiblyExactOperator>(V)) + if (isa<PossiblyExactOperator>(this)) + setIsExact(isExact() & PE->isExact()); + + if (auto *FP = dyn_cast<FPMathOperator>(V)) { + if (isa<FPMathOperator>(this)) { + FastMathFlags FM = getFastMathFlags(); + FM &= FP->getFastMathFlags(); + copyFastMathFlags(FM); + } + } + + if (auto *SrcGEP = dyn_cast<GetElementPtrInst>(V)) + if (auto *DestGEP = dyn_cast<GetElementPtrInst>(this)) + DestGEP->setIsInBounds(SrcGEP->isInBounds() & DestGEP->isInBounds()); +} const char *Instruction::getOpcodeName(unsigned OpCode) { switch (OpCode) { @@ -271,13 +324,18 @@ } } -/// Return true if both instructions have the same special state -/// This must be kept in sync with lib/Transforms/IPO/MergeFunctions.cpp. +/// Return true if both instructions have the same special state. This must be +/// kept in sync with FunctionComparator::cmpOperations in +/// lib/Transforms/IPO/MergeFunctions.cpp. static bool haveSameSpecialState(const Instruction *I1, const Instruction *I2, bool IgnoreAlignment = false) { assert(I1->getOpcode() == I2->getOpcode() && "Can not compare special state of different instructions"); + if (const AllocaInst *AI = dyn_cast<AllocaInst>(I1)) + return AI->getAllocatedType() == cast<AllocaInst>(I2)->getAllocatedType() && + (AI->getAlignment() == cast<AllocaInst>(I2)->getAlignment() || + IgnoreAlignment); if (const LoadInst *LI = dyn_cast<LoadInst>(I1)) return LI->isVolatile() == cast<LoadInst>(I2)->isVolatile() && (LI->getAlignment() == cast<LoadInst>(I2)->getAlignment() || @@ -325,17 +383,11 @@ return true; } -/// isIdenticalTo - Return true if the specified instruction is exactly -/// identical to the current one. This means that all operands match and any -/// extra information (e.g. load is volatile) agree. bool Instruction::isIdenticalTo(const Instruction *I) const { return isIdenticalToWhenDefined(I) && SubclassOptionalData == I->SubclassOptionalData; } -/// isIdenticalToWhenDefined - This is like isIdenticalTo, except that it -/// ignores the SubclassOptionalData flags, which specify conditions -/// under which the instruction's result is undefined. bool Instruction::isIdenticalToWhenDefined(const Instruction *I) const { if (getOpcode() != I->getOpcode() || getNumOperands() != I->getNumOperands() || @@ -360,8 +412,7 @@ return haveSameSpecialState(this, I); } -// isSameOperationAs -// This should be kept in sync with isEquivalentOperation in +// Keep this in sync with FunctionComparator::cmpOperations in // lib/Transforms/IPO/MergeFunctions.cpp. bool Instruction::isSameOperationAs(const Instruction *I, unsigned flags) const { @@ -387,9 +438,6 @@ return haveSameSpecialState(this, I, IgnoreAlignment); } -/// isUsedOutsideOfBlock - Return true if there are any uses of I outside of the -/// specified block. Note that PHI nodes are considered to evaluate their -/// operands in the corresponding predecessor block. bool Instruction::isUsedOutsideOfBlock(const BasicBlock *BB) const { for (const Use &U : uses()) { // PHI nodes uses values in the corresponding predecessor block. For other @@ -408,8 +456,6 @@ return false; } -/// mayReadFromMemory - Return true if this instruction may read memory. -/// bool Instruction::mayReadFromMemory() const { switch (getOpcode()) { default: return false; @@ -430,8 +476,6 @@ } } -/// mayWriteToMemory - Return true if this instruction may modify memory. -/// bool Instruction::mayWriteToMemory() const { switch (getOpcode()) { default: return false; @@ -461,9 +505,9 @@ case Instruction::Fence: return true; case Instruction::Load: - return cast<LoadInst>(this)->getOrdering() != NotAtomic; + return cast<LoadInst>(this)->getOrdering() != AtomicOrdering::NotAtomic; case Instruction::Store: - return cast<StoreInst>(this)->getOrdering() != NotAtomic; + return cast<StoreInst>(this)->getOrdering() != AtomicOrdering::NotAtomic; } } @@ -477,13 +521,7 @@ return isa<ResumeInst>(this); } -bool Instruction::mayReturn() const { - if (const CallInst *CI = dyn_cast<CallInst>(this)) - return !CI->doesNotReturn(); - return true; -} - -/// isAssociative - Return true if the instruction is associative: +/// Return true if the instruction is associative: /// /// Associative operators satisfy: x op (y op z) === (x op y) op z /// @@ -508,7 +546,7 @@ } } -/// isCommutative - Return true if the instruction is commutative: +/// Return true if the instruction is commutative: /// /// Commutative operators satisfy: (x op y) === (y op x) /// @@ -530,7 +568,7 @@ } } -/// isIdempotent - Return true if the instruction is idempotent: +/// Return true if the instruction is idempotent: /// /// Idempotent operators satisfy: x op x === x /// @@ -540,7 +578,7 @@ return Opcode == And || Opcode == Or; } -/// isNilpotent - Return true if the instruction is nilpotent: +/// Return true if the instruction is nilpotent: /// /// Nilpotent operators satisfy: x op x === Id, /// @@ -557,6 +595,45 @@ llvm_unreachable("Subclass of Instruction failed to implement cloneImpl"); } +void Instruction::swapProfMetadata() { + MDNode *ProfileData = getMetadata(LLVMContext::MD_prof); + if (!ProfileData || ProfileData->getNumOperands() != 3 || + !isa<MDString>(ProfileData->getOperand(0))) + return; + + MDString *MDName = cast<MDString>(ProfileData->getOperand(0)); + if (MDName->getString() != "branch_weights") + return; + + // The first operand is the name. Fetch them backwards and build a new one. + Metadata *Ops[] = {ProfileData->getOperand(0), ProfileData->getOperand(2), + ProfileData->getOperand(1)}; + setMetadata(LLVMContext::MD_prof, + MDNode::get(ProfileData->getContext(), Ops)); +} + +void Instruction::copyMetadata(const Instruction &SrcInst, + ArrayRef<unsigned> WL) { + if (!SrcInst.hasMetadata()) + return; + + DenseSet<unsigned> WLS; + for (unsigned M : WL) + WLS.insert(M); + + // Otherwise, enumerate and copy over metadata from the old instruction to the + // new one. + SmallVector<std::pair<unsigned, MDNode *>, 4> TheMDs; + SrcInst.getAllMetadataOtherThanDebugLoc(TheMDs); + for (const auto &MD : TheMDs) { + if (WL.empty() || WLS.count(MD.first)) + setMetadata(MD.first, MD.second); + } + if (WL.empty() || WLS.count(LLVMContext::MD_dbg)) + setDebugLoc(SrcInst.getDebugLoc()); + return; +} + Instruction *Instruction::clone() const { Instruction *New = nullptr; switch (getOpcode()) { @@ -571,16 +648,6 @@ } New->SubclassOptionalData = SubclassOptionalData; - if (!hasMetadata()) - return New; - - // Otherwise, enumerate and copy over metadata from the old instruction to the - // new one. - SmallVector<std::pair<unsigned, MDNode *>, 4> TheMDs; - getAllMetadataOtherThanDebugLoc(TheMDs); - for (const auto &MD : TheMDs) - New->setMetadata(MD.first, MD.second); - - New->setDebugLoc(getDebugLoc()); + New->copyMetadata(*this); return New; }