[llvm] 0c2b09a - [IR] Lazily number instructions for local dominance queries
Vedant Kumar via llvm-commits
llvm-commits at lists.llvm.org
Thu Feb 20 13:10:07 PST 2020
Wdyt of having DominatorTree take advantage of the instruction ordering? Istm this is needed to allow various clients in llvm to get rid of special handling for block-local queries.
--- a/llvm/lib/IR/Dominators.cpp
+++ b/llvm/lib/IR/Dominators.cpp
@@ -138,16 +138,11 @@ bool DominatorTree::dominates(const Instruction *Def,
return dominates(Def, UseBB);
if (DefBB != UseBB)
return dominates(DefBB, UseBB);
- // Loop through the basic block until we find Def or User.
- BasicBlock::const_iterator I = DefBB->begin();
- for (; &*I != Def && &*I != User; ++I)
- /*empty*/;
-
- return &*I == Def;
+ return Def->comesBefore(User);
}
vedant
> On Feb 18, 2020, at 2:46 PM, Reid Kleckner via llvm-commits <llvm-commits at lists.llvm.org> wrote:
>
>
> Author: Reid Kleckner
> Date: 2020-02-18T14:44:24-08:00
> New Revision: 0c2b09a9b6246aebd301ad75b5d78ac1e7daa9c4
>
> URL: https://github.com/llvm/llvm-project/commit/0c2b09a9b6246aebd301ad75b5d78ac1e7daa9c4
> DIFF: https://github.com/llvm/llvm-project/commit/0c2b09a9b6246aebd301ad75b5d78ac1e7daa9c4.diff
>
> LOG: [IR] Lazily number instructions for local dominance queries
>
> Essentially, fold OrderedBasicBlock into BasicBlock, and make it
> auto-invalidate the instruction ordering when new instructions are
> added. Notably, we don't need to invalidate it when removing
> instructions, which is helpful when a pass mostly delete dead
> instructions rather than transforming them.
>
> The downside is that Instruction grows from 56 bytes to 64 bytes. The
> resulting LLVM code is substantially simpler and automatically handles
> invalidation, which makes me think that this is the right speed and size
> tradeoff.
>
> The important change is in SymbolTableTraitsImpl.h, where the numbering
> is invalidated. Everything else should be straightforward.
>
> We probably want to implement a fancier re-numbering scheme so that
> local updates don't invalidate the ordering, but I plan for that to be
> future work, maybe for someone else.
>
> Reviewed By: lattner, vsk, fhahn, dexonsmith
>
> Differential Revision: https://reviews.llvm.org/D51664
>
> Added:
>
>
> Modified:
> llvm/include/llvm/Analysis/AliasAnalysis.h
> llvm/include/llvm/Analysis/CaptureTracking.h
> llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h
> llvm/include/llvm/Analysis/OrderedInstructions.h
> llvm/include/llvm/IR/BasicBlock.h
> llvm/include/llvm/IR/Instruction.h
> llvm/lib/Analysis/AliasAnalysis.cpp
> llvm/lib/Analysis/CMakeLists.txt
> llvm/lib/Analysis/CaptureTracking.cpp
> llvm/lib/Analysis/InstructionPrecedenceTracking.cpp
> llvm/lib/Analysis/MemoryDependenceAnalysis.cpp
> llvm/lib/Analysis/OrderedInstructions.cpp
> llvm/lib/IR/BasicBlock.cpp
> llvm/lib/IR/Instruction.cpp
> llvm/lib/IR/SymbolTableListTraitsImpl.h
> llvm/lib/Target/ARM/ARMParallelDSP.cpp
> llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
> llvm/lib/Transforms/Vectorize/LoadStoreVectorizer.cpp
> llvm/unittests/Analysis/CMakeLists.txt
> llvm/unittests/Analysis/CaptureTrackingTest.cpp
> llvm/unittests/IR/BasicBlockTest.cpp
> llvm/utils/gn/secondary/llvm/lib/Analysis/BUILD.gn
> llvm/utils/gn/secondary/llvm/unittests/Analysis/BUILD.gn
>
> Removed:
> llvm/include/llvm/Analysis/OrderedBasicBlock.h
> llvm/lib/Analysis/OrderedBasicBlock.cpp
> llvm/unittests/Analysis/OrderedBasicBlockTest.cpp
>
>
> ################################################################################
> diff --git a/llvm/include/llvm/Analysis/AliasAnalysis.h b/llvm/include/llvm/Analysis/AliasAnalysis.h
> index a285909a9310..95b4c2a482b2 100644
> --- a/llvm/include/llvm/Analysis/AliasAnalysis.h
> +++ b/llvm/include/llvm/Analysis/AliasAnalysis.h
> @@ -59,7 +59,6 @@ class AnalysisUsage;
> class BasicAAResult;
> class BasicBlock;
> class DominatorTree;
> -class OrderedBasicBlock;
> class Value;
>
> /// The possible results of an alias query.
> @@ -689,19 +688,16 @@ class AAResults {
>
> /// Return information about whether a particular call site modifies
> /// or reads the specified memory location \p MemLoc before instruction \p I
> - /// in a BasicBlock. An ordered basic block \p OBB can be used to speed up
> - /// instruction ordering queries inside the BasicBlock containing \p I.
> + /// in a BasicBlock.
> /// Early exits in callCapturesBefore may lead to ModRefInfo::Must not being
> /// set.
> ModRefInfo callCapturesBefore(const Instruction *I,
> - const MemoryLocation &MemLoc, DominatorTree *DT,
> - OrderedBasicBlock *OBB = nullptr);
> + const MemoryLocation &MemLoc, DominatorTree *DT);
>
> /// A convenience wrapper to synthesize a memory location.
> ModRefInfo callCapturesBefore(const Instruction *I, const Value *P,
> - LocationSize Size, DominatorTree *DT,
> - OrderedBasicBlock *OBB = nullptr) {
> - return callCapturesBefore(I, MemoryLocation(P, Size), DT, OBB);
> + LocationSize Size, DominatorTree *DT) {
> + return callCapturesBefore(I, MemoryLocation(P, Size), DT);
> }
>
> /// @}
>
> diff --git a/llvm/include/llvm/Analysis/CaptureTracking.h b/llvm/include/llvm/Analysis/CaptureTracking.h
> index 29921a51d5be..5f72f82f9566 100644
> --- a/llvm/include/llvm/Analysis/CaptureTracking.h
> +++ b/llvm/include/llvm/Analysis/CaptureTracking.h
> @@ -20,7 +20,6 @@ namespace llvm {
> class DataLayout;
> class Instruction;
> class DominatorTree;
> - class OrderedBasicBlock;
>
> /// The default value for MaxUsesToExplore argument. It's relatively small to
> /// keep the cost of analysis reasonable for clients like BasicAliasAnalysis,
> @@ -53,14 +52,12 @@ namespace llvm {
> /// it or not. The boolean StoreCaptures specified whether storing the value
> /// (or part of it) into memory anywhere automatically counts as capturing it
> /// or not. Captures by the provided instruction are considered if the
> - /// final parameter is true. An ordered basic block in \p OBB could be used
> - /// to speed up capture-tracker queries.
> + /// final parameter is true.
> /// MaxUsesToExplore specifies how many uses should the analysis explore for
> /// one value before giving up due too "too many uses".
> bool PointerMayBeCapturedBefore(const Value *V, bool ReturnCaptures,
> bool StoreCaptures, const Instruction *I,
> const DominatorTree *DT, bool IncludeI = false,
> - OrderedBasicBlock *OBB = nullptr,
> unsigned MaxUsesToExplore = DefaultMaxUsesToExplore);
>
> /// This callback is used in conjunction with PointerMayBeCaptured. In
>
> diff --git a/llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h b/llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h
> index a1ebb950b59a..6869ff2aafa5 100644
> --- a/llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h
> +++ b/llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h
> @@ -384,8 +384,7 @@ class MemoryDependenceResults {
> ///
> /// See the class comment for more details. It is illegal to call this on
> /// non-memory instructions.
> - MemDepResult getDependency(Instruction *QueryInst,
> - OrderedBasicBlock *OBB = nullptr);
> + MemDepResult getDependency(Instruction *QueryInst);
>
> /// Perform a full dependency query for the specified call, returning the set
> /// of blocks that the value is potentially live across.
> @@ -451,14 +450,12 @@ class MemoryDependenceResults {
> BasicBlock::iterator ScanIt,
> BasicBlock *BB,
> Instruction *QueryInst = nullptr,
> - unsigned *Limit = nullptr,
> - OrderedBasicBlock *OBB = nullptr);
> + unsigned *Limit = nullptr);
>
> MemDepResult
> getSimplePointerDependencyFrom(const MemoryLocation &MemLoc, bool isLoad,
> BasicBlock::iterator ScanIt, BasicBlock *BB,
> - Instruction *QueryInst, unsigned *Limit,
> - OrderedBasicBlock *OBB);
> + Instruction *QueryInst, unsigned *Limit);
>
> /// This analysis looks for other loads and stores with invariant.group
> /// metadata and the same pointer operand. Returns Unknown if it does not
>
> diff --git a/llvm/include/llvm/Analysis/OrderedBasicBlock.h b/llvm/include/llvm/Analysis/OrderedBasicBlock.h
> deleted file mode 100644
> index ae64c0189f5e..000000000000
> --- a/llvm/include/llvm/Analysis/OrderedBasicBlock.h
> +++ /dev/null
> @@ -1,74 +0,0 @@
> -//===- llvm/Analysis/OrderedBasicBlock.h --------------------- -*- 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 the OrderedBasicBlock class. OrderedBasicBlock maintains
> -// an interface where clients can query if one instruction comes before another
> -// in a BasicBlock. Since BasicBlock currently lacks a reliable way to query
> -// relative position between instructions one can use OrderedBasicBlock to do
> -// such queries. OrderedBasicBlock is lazily built on a source BasicBlock and
> -// maintains an internal Instruction -> Position map. A OrderedBasicBlock
> -// instance should be discarded whenever the source BasicBlock changes.
> -//
> -// It's currently used by the CaptureTracker in order to find relative
> -// positions of a pair of instructions inside a BasicBlock.
> -//
> -//===----------------------------------------------------------------------===//
> -
> -#ifndef LLVM_ANALYSIS_ORDEREDBASICBLOCK_H
> -#define LLVM_ANALYSIS_ORDEREDBASICBLOCK_H
> -
> -#include "llvm/ADT/DenseMap.h"
> -#include "llvm/IR/BasicBlock.h"
> -
> -namespace llvm {
> -
> -class Instruction;
> -class BasicBlock;
> -
> -class OrderedBasicBlock {
> -private:
> - /// Map a instruction to its position in a BasicBlock.
> - SmallDenseMap<const Instruction *, unsigned, 32> NumberedInsts;
> -
> - /// Keep track of last instruction inserted into \p NumberedInsts.
> - /// It speeds up queries for uncached instructions by providing a start point
> - /// for new queries in OrderedBasicBlock::comesBefore.
> - BasicBlock::const_iterator LastInstFound;
> -
> - /// The position/number to tag the next instruction to be found.
> - unsigned NextInstPos;
> -
> - /// The source BasicBlock to map.
> - const BasicBlock *BB;
> -
> - /// Given no cached results, find if \p A comes before \p B in \p BB.
> - /// Cache and number out instruction while walking \p BB.
> - bool comesBefore(const Instruction *A, const Instruction *B);
> -
> -public:
> - OrderedBasicBlock(const BasicBlock *BasicB);
> -
> - /// Find out whether \p A dominates \p B, meaning whether \p A
> - /// comes before \p B in \p BB. This is a simplification that considers
> - /// cached instruction positions and ignores other basic blocks, being
> - /// only relevant to compare relative instructions positions inside \p BB.
> - /// Returns false for A == B.
> - bool dominates(const Instruction *A, const Instruction *B);
> -
> - /// Remove \p from the ordering, if it is present.
> - void eraseInstruction(const Instruction *I);
> -
> - /// Replace \p Old with \p New in the ordering. \p New is assigned the
> - /// numbering of \p Old, so it must be inserted at the same position in the
> - /// IR.
> - void replaceInstruction(const Instruction *Old, const Instruction *New);
> -};
> -
> -} // End llvm namespace
> -
> -#endif
>
> diff --git a/llvm/include/llvm/Analysis/OrderedInstructions.h b/llvm/include/llvm/Analysis/OrderedInstructions.h
> index 967b146b52de..302509380a03 100644
> --- a/llvm/include/llvm/Analysis/OrderedInstructions.h
> +++ b/llvm/include/llvm/Analysis/OrderedInstructions.h
> @@ -9,10 +9,9 @@
> // This file defines an efficient way to check for dominance relation between 2
> // instructions.
> //
> -// This interface dispatches to appropriate dominance check given 2
> -// instructions, i.e. in case the instructions are in the same basic block,
> -// OrderedBasicBlock (with instruction numbering and caching) are used.
> -// Otherwise, dominator tree is used.
> +// FIXME: This is really just a convenience wrapper to check dominance between
> +// two arbitrary instructions in
> diff erent basic blocks. We should fold it into
> +// DominatorTree, which is the more widely used interface.
> //
> //===----------------------------------------------------------------------===//
>
> @@ -20,17 +19,12 @@
> #define LLVM_ANALYSIS_ORDEREDINSTRUCTIONS_H
>
> #include "llvm/ADT/DenseMap.h"
> -#include "llvm/Analysis/OrderedBasicBlock.h"
> #include "llvm/IR/Dominators.h"
> #include "llvm/IR/Operator.h"
>
> namespace llvm {
>
> class OrderedInstructions {
> - /// Used to check dominance for instructions in same basic block.
> - mutable DenseMap<const BasicBlock *, std::unique_ptr<OrderedBasicBlock>>
> - OBBMap;
> -
> /// The dominator tree of the parent function.
> DominatorTree *DT;
>
> @@ -51,12 +45,6 @@ class OrderedInstructions {
> /// or if the first instruction comes before the second in the same basic
> /// block.
> bool dfsBefore(const Instruction *, const Instruction *) const;
> -
> - /// Invalidate the OrderedBasicBlock cache when its basic block changes.
> - /// i.e. If an instruction is deleted or added to the basic block, the user
> - /// should call this function to invalidate the OrderedBasicBlock cache for
> - /// this basic block.
> - void invalidateBlock(const BasicBlock *BB) { OBBMap.erase(BB); }
> };
>
> } // end namespace llvm
>
> diff --git a/llvm/include/llvm/IR/BasicBlock.h b/llvm/include/llvm/IR/BasicBlock.h
> index 7cfe7b181b1c..51150787a986 100644
> --- a/llvm/include/llvm/IR/BasicBlock.h
> +++ b/llvm/include/llvm/IR/BasicBlock.h
> @@ -402,7 +402,9 @@ class BasicBlock final : public Value, // Basic blocks are data objects also
>
> /// Returns true if there are any uses of this basic block other than
> /// direct branches, switches, etc. to it.
> - bool hasAddressTaken() const { return getSubclassDataFromValue() != 0; }
> + bool hasAddressTaken() const {
> + return getBasicBlockBits().BlockAddressRefCount != 0;
> + }
>
> /// Update all phi nodes in this basic block to refer to basic block \p New
> /// instead of basic block \p Old.
> @@ -437,16 +439,61 @@ class BasicBlock final : public Value, // Basic blocks are data objects also
>
> Optional<uint64_t> getIrrLoopHeaderWeight() const;
>
> + /// Returns true if the Order field of child Instructions is valid.
> + bool isInstrOrderValid() const {
> + return getBasicBlockBits().InstrOrderValid;
> + }
> +
> + /// Mark instruction ordering invalid. Done on every instruction insert.
> + void invalidateOrders() {
> + validateInstrOrdering();
> + BasicBlockBits Bits = getBasicBlockBits();
> + Bits.InstrOrderValid = false;
> + setBasicBlockBits(Bits);
> + }
> +
> + /// Renumber instructions and mark the ordering as valid.
> + void renumberInstructions();
> +
> + /// Returns false if the instruction ordering is incorrect in an debug build.
> + /// Always returns true when assertions are disabled. The method does not
> + /// assert internally so that we get better location info.
> + void validateInstrOrdering() const;
> +
> private:
> + /// Bitfield to help interpret the bits in Value::SubclassData.
> + struct BasicBlockBits {
> + unsigned short BlockAddressRefCount : 15;
> + unsigned short InstrOrderValid : 1;
> + };
> +
> + /// Safely reinterpret the subclass data bits to a more useful form.
> + BasicBlockBits getBasicBlockBits() const {
> + static_assert(sizeof(BasicBlockBits) == sizeof(unsigned short),
> + "too many bits for Value::SubclassData");
> + unsigned short ValueData = getSubclassDataFromValue();
> + BasicBlockBits AsBits;
> + memcpy(&AsBits, &ValueData, sizeof(AsBits));
> + return AsBits;
> + }
> +
> + /// Reinterpret our subclass bits and store them back into Value.
> + void setBasicBlockBits(BasicBlockBits AsBits) {
> + unsigned short D;
> + memcpy(&D, &AsBits, sizeof(D));
> + Value::setValueSubclassData(D);
> + }
> +
> /// Increment the internal refcount of the number of BlockAddresses
> /// referencing this BasicBlock by \p Amt.
> ///
> /// This is almost always 0, sometimes one possibly, but almost never 2, and
> /// inconceivably 3 or more.
> void AdjustBlockAddressRefCount(int Amt) {
> - setValueSubclassData(getSubclassDataFromValue()+Amt);
> - assert((int)(signed char)getSubclassDataFromValue() >= 0 &&
> - "Refcount wrap-around");
> + BasicBlockBits Bits = getBasicBlockBits();
> + Bits.BlockAddressRefCount += Amt;
> + setBasicBlockBits(Bits);
> + assert(Bits.BlockAddressRefCount < 255 && "Refcount wrap-around");
> }
>
> /// Shadow Value::setValueSubclassData with a private forwarding method so
> @@ -463,6 +510,12 @@ DEFINE_SIMPLE_CONVERSION_FUNCTIONS(BasicBlock, LLVMBasicBlockRef)
> /// This assumes that \p It is not at the end of a block.
> BasicBlock::iterator skipDebugIntrinsics(BasicBlock::iterator It);
>
> +#ifdef NDEBUG
> +/// In release builds, this is a no-op. For !NDEBUG builds, the checks are
> +/// implemented in the .cpp file to avoid circular header deps.
> +inline void Instruction::validateInstrOrdering() const {}
> +#endif
> +
> } // end namespace llvm
>
> #endif // LLVM_IR_BASICBLOCK_H
>
> diff --git a/llvm/include/llvm/IR/Instruction.h b/llvm/include/llvm/IR/Instruction.h
> index 3bfa0e4afc39..b15ececc677c 100644
> --- a/llvm/include/llvm/IR/Instruction.h
> +++ b/llvm/include/llvm/IR/Instruction.h
> @@ -45,6 +45,10 @@ class Instruction : public User,
> BasicBlock *Parent;
> DebugLoc DbgLoc; // 'dbg' Metadata cache.
>
> + /// Relative order of this instruction in its parent basic block. Used for
> + /// O(1) local dominance checks between instructions.
> + mutable unsigned Order = 0;
> +
> enum {
> /// This is a bit stored in the SubClassData field which indicates whether
> /// this instruction has metadata attached to it or not.
> @@ -117,6 +121,13 @@ class Instruction : public User,
> /// the basic block that MovePos lives in, right after MovePos.
> void moveAfter(Instruction *MovePos);
>
> + /// Given an instruction Other in the same basic block as this instruction,
> + /// return true if this instruction comes before Other. In this worst case,
> + /// this takes linear time in the number of instructions in the block. The
> + /// results are cached, so in common cases when the block remains unmodified,
> + /// it takes constant time.
> + bool comesBefore(const Instruction *Other) const;
> +
> //===--------------------------------------------------------------------===//
> // Subclass classification.
> //===--------------------------------------------------------------------===//
> @@ -738,6 +749,7 @@ class Instruction : public User,
>
> private:
> friend class SymbolTableListTraits<Instruction>;
> + friend class BasicBlock; // For renumbering.
>
> // Shadow Value::setValueSubclassData with a private forwarding method so that
> // subclasses cannot accidentally use it.
>
> diff --git a/llvm/lib/Analysis/AliasAnalysis.cpp b/llvm/lib/Analysis/AliasAnalysis.cpp
> index 9d18ffa72ac8..9db816ef1fda 100644
> --- a/llvm/lib/Analysis/AliasAnalysis.cpp
> +++ b/llvm/lib/Analysis/AliasAnalysis.cpp
> @@ -630,16 +630,14 @@ ModRefInfo AAResults::getModRefInfo(const AtomicRMWInst *RMW,
>
> /// Return information about whether a particular call site modifies
> /// or reads the specified memory location \p MemLoc before instruction \p I
> -/// in a BasicBlock. An ordered basic block \p OBB can be used to speed up
> -/// instruction-ordering queries inside the BasicBlock containing \p I.
> +/// in a BasicBlock.
> /// FIXME: this is really just shoring-up a deficiency in alias analysis.
> /// BasicAA isn't willing to spend linear time determining whether an alloca
> /// was captured before or after this particular call, while we are. However,
> /// with a smarter AA in place, this test is just wasting compile time.
> ModRefInfo AAResults::callCapturesBefore(const Instruction *I,
> const MemoryLocation &MemLoc,
> - DominatorTree *DT,
> - OrderedBasicBlock *OBB) {
> + DominatorTree *DT) {
> if (!DT)
> return ModRefInfo::ModRef;
>
> @@ -655,8 +653,7 @@ ModRefInfo AAResults::callCapturesBefore(const Instruction *I,
>
> if (PointerMayBeCapturedBefore(Object, /* ReturnCaptures */ true,
> /* StoreCaptures */ true, I, DT,
> - /* include Object */ true,
> - /* OrderedBasicBlock */ OBB))
> + /* include Object */ true))
> return ModRefInfo::ModRef;
>
> unsigned ArgNo = 0;
>
> diff --git a/llvm/lib/Analysis/CMakeLists.txt b/llvm/lib/Analysis/CMakeLists.txt
> index cc9ff0bc1f57..34140e18677d 100644
> --- a/llvm/lib/Analysis/CMakeLists.txt
> +++ b/llvm/lib/Analysis/CMakeLists.txt
> @@ -70,7 +70,6 @@ add_llvm_component_library(LLVMAnalysis
> ObjCARCAnalysisUtils.cpp
> ObjCARCInstKind.cpp
> OptimizationRemarkEmitter.cpp
> - OrderedBasicBlock.cpp
> OrderedInstructions.cpp
> PHITransAddr.cpp
> PhiValues.cpp
>
> diff --git a/llvm/lib/Analysis/CaptureTracking.cpp b/llvm/lib/Analysis/CaptureTracking.cpp
> index 20e2f06540a3..3d1f266a2e57 100644
> --- a/llvm/lib/Analysis/CaptureTracking.cpp
> +++ b/llvm/lib/Analysis/CaptureTracking.cpp
> @@ -20,7 +20,6 @@
> #include "llvm/ADT/SmallVector.h"
> #include "llvm/Analysis/AliasAnalysis.h"
> #include "llvm/Analysis/CFG.h"
> -#include "llvm/Analysis/OrderedBasicBlock.h"
> #include "llvm/Analysis/ValueTracking.h"
> #include "llvm/IR/Constants.h"
> #include "llvm/IR/Dominators.h"
> @@ -76,8 +75,8 @@ namespace {
> struct CapturesBefore : public CaptureTracker {
>
> CapturesBefore(bool ReturnCaptures, const Instruction *I, const DominatorTree *DT,
> - bool IncludeI, OrderedBasicBlock *IC)
> - : OrderedBB(IC), BeforeHere(I), DT(DT),
> + bool IncludeI)
> + : BeforeHere(I), DT(DT),
> ReturnCaptures(ReturnCaptures), IncludeI(IncludeI), Captured(false) {}
>
> void tooManyUses() override { Captured = true; }
> @@ -90,9 +89,7 @@ namespace {
> return true;
>
> // Compute the case where both instructions are inside the same basic
> - // block. Since instructions in the same BB as BeforeHere are numbered in
> - // 'OrderedBB', avoid using 'dominates' and 'isPotentiallyReachable'
> - // which are very expensive for large basic blocks.
> + // block.
> if (BB == BeforeHere->getParent()) {
> // 'I' dominates 'BeforeHere' => not safe to prune.
> //
> @@ -102,7 +99,7 @@ namespace {
> // UseBB == BB, avoid pruning.
> if (isa<InvokeInst>(BeforeHere) || isa<PHINode>(I) || I == BeforeHere)
> return false;
> - if (!OrderedBB->dominates(BeforeHere, I))
> + if (!BeforeHere->comesBefore(I))
> return false;
>
> // 'BeforeHere' comes before 'I', it's safe to prune if we also
> @@ -153,7 +150,6 @@ namespace {
> return true;
> }
>
> - OrderedBasicBlock *OrderedBB;
> const Instruction *BeforeHere;
> const DominatorTree *DT;
>
> @@ -196,31 +192,23 @@ bool llvm::PointerMayBeCaptured(const Value *V,
> /// returning the value (or part of it) from the function counts as capturing
> /// it or not. The boolean StoreCaptures specified whether storing the value
> /// (or part of it) into memory anywhere automatically counts as capturing it
> -/// or not. A ordered basic block \p OBB can be used in order to speed up
> -/// queries about relative order among instructions in the same basic block.
> +/// or not.
> bool llvm::PointerMayBeCapturedBefore(const Value *V, bool ReturnCaptures,
> bool StoreCaptures, const Instruction *I,
> const DominatorTree *DT, bool IncludeI,
> - OrderedBasicBlock *OBB,
> unsigned MaxUsesToExplore) {
> assert(!isa<GlobalValue>(V) &&
> "It doesn't make sense to ask whether a global is captured.");
> - bool UseNewOBB = OBB == nullptr;
>
> if (!DT)
> return PointerMayBeCaptured(V, ReturnCaptures, StoreCaptures,
> MaxUsesToExplore);
> - if (UseNewOBB)
> - OBB = new OrderedBasicBlock(I->getParent());
>
> // TODO: See comment in PointerMayBeCaptured regarding what could be done
> // with StoreCaptures.
>
> - CapturesBefore CB(ReturnCaptures, I, DT, IncludeI, OBB);
> + CapturesBefore CB(ReturnCaptures, I, DT, IncludeI);
> PointerMayBeCaptured(V, &CB, MaxUsesToExplore);
> -
> - if (UseNewOBB)
> - delete OBB;
> return CB.Captured;
> }
>
>
> diff --git a/llvm/lib/Analysis/InstructionPrecedenceTracking.cpp b/llvm/lib/Analysis/InstructionPrecedenceTracking.cpp
> index 415797d6a378..3f5a161c8659 100644
> --- a/llvm/lib/Analysis/InstructionPrecedenceTracking.cpp
> +++ b/llvm/lib/Analysis/InstructionPrecedenceTracking.cpp
> @@ -104,18 +104,14 @@ void InstructionPrecedenceTracking::insertInstructionTo(const Instruction *Inst,
> const BasicBlock *BB) {
> if (isSpecialInstruction(Inst))
> FirstSpecialInsts.erase(BB);
> - OI.invalidateBlock(BB);
> }
>
> void InstructionPrecedenceTracking::removeInstruction(const Instruction *Inst) {
> if (isSpecialInstruction(Inst))
> FirstSpecialInsts.erase(Inst->getParent());
> - OI.invalidateBlock(Inst->getParent());
> }
>
> void InstructionPrecedenceTracking::clear() {
> - for (auto It : FirstSpecialInsts)
> - OI.invalidateBlock(It.first);
> FirstSpecialInsts.clear();
> #ifndef NDEBUG
> // The map should be valid after clearing (at least empty).
>
> diff --git a/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp b/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp
> index 450595cac57b..2b01dc43a687 100644
> --- a/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp
> +++ b/llvm/lib/Analysis/MemoryDependenceAnalysis.cpp
> @@ -23,7 +23,6 @@
> #include "llvm/Analysis/AssumptionCache.h"
> #include "llvm/Analysis/MemoryBuiltins.h"
> #include "llvm/Analysis/MemoryLocation.h"
> -#include "llvm/Analysis/OrderedBasicBlock.h"
> #include "llvm/Analysis/PHITransAddr.h"
> #include "llvm/Analysis/PhiValues.h"
> #include "llvm/Analysis/TargetLibraryInfo.h"
> @@ -250,8 +249,7 @@ static bool isVolatile(Instruction *Inst) {
>
> MemDepResult MemoryDependenceResults::getPointerDependencyFrom(
> const MemoryLocation &MemLoc, bool isLoad, BasicBlock::iterator ScanIt,
> - BasicBlock *BB, Instruction *QueryInst, unsigned *Limit,
> - OrderedBasicBlock *OBB) {
> + BasicBlock *BB, Instruction *QueryInst, unsigned *Limit) {
> MemDepResult InvariantGroupDependency = MemDepResult::getUnknown();
> if (QueryInst != nullptr) {
> if (auto *LI = dyn_cast<LoadInst>(QueryInst)) {
> @@ -262,7 +260,7 @@ MemDepResult MemoryDependenceResults::getPointerDependencyFrom(
> }
> }
> MemDepResult SimpleDep = getSimplePointerDependencyFrom(
> - MemLoc, isLoad, ScanIt, BB, QueryInst, Limit, OBB);
> + MemLoc, isLoad, ScanIt, BB, QueryInst, Limit);
> if (SimpleDep.isDef())
> return SimpleDep;
> // Non-local invariant group dependency indicates there is non local Def
> @@ -363,8 +361,7 @@ MemoryDependenceResults::getInvariantGroupPointerDependency(LoadInst *LI,
>
> MemDepResult MemoryDependenceResults::getSimplePointerDependencyFrom(
> const MemoryLocation &MemLoc, bool isLoad, BasicBlock::iterator ScanIt,
> - BasicBlock *BB, Instruction *QueryInst, unsigned *Limit,
> - OrderedBasicBlock *OBB) {
> + BasicBlock *BB, Instruction *QueryInst, unsigned *Limit) {
> bool isInvariantLoad = false;
>
> unsigned DefaultLimit = getDefaultBlockScanLimit();
> @@ -411,15 +408,6 @@ MemDepResult MemoryDependenceResults::getSimplePointerDependencyFrom(
>
> const DataLayout &DL = BB->getModule()->getDataLayout();
>
> - // If the caller did not provide an ordered basic block,
> - // create one to lazily compute and cache instruction
> - // positions inside a BB. This is used to provide fast queries for relative
> - // position between two instructions in a BB and can be used by
> - // AliasAnalysis::callCapturesBefore.
> - OrderedBasicBlock OBBTmp(BB);
> - if (!OBB)
> - OBB = &OBBTmp;
> -
> // Return "true" if and only if the instruction I is either a non-simple
> // load or a non-simple store.
> auto isNonSimpleLoadOrStore = [](Instruction *I) -> bool {
> @@ -609,7 +597,7 @@ MemDepResult MemoryDependenceResults::getSimplePointerDependencyFrom(
> ModRefInfo MR = AA.getModRefInfo(Inst, MemLoc);
> // If necessary, perform additional analysis.
> if (isModAndRefSet(MR))
> - MR = AA.callCapturesBefore(Inst, MemLoc, &DT, OBB);
> + MR = AA.callCapturesBefore(Inst, MemLoc, &DT);
> switch (clearMust(MR)) {
> case ModRefInfo::NoModRef:
> // If the call has no effect on the queried pointer, just ignore it.
> @@ -635,8 +623,7 @@ MemDepResult MemoryDependenceResults::getSimplePointerDependencyFrom(
> return MemDepResult::getNonFuncLocal();
> }
>
> -MemDepResult MemoryDependenceResults::getDependency(Instruction *QueryInst,
> - OrderedBasicBlock *OBB) {
> +MemDepResult MemoryDependenceResults::getDependency(Instruction *QueryInst) {
> Instruction *ScanPos = QueryInst;
>
> // Check for a cached result
> @@ -676,7 +663,7 @@ MemDepResult MemoryDependenceResults::getDependency(Instruction *QueryInst,
>
> LocalCache =
> getPointerDependencyFrom(MemLoc, isLoad, ScanPos->getIterator(),
> - QueryParent, QueryInst, nullptr, OBB);
> + QueryParent, QueryInst, nullptr);
> } else if (auto *QueryCall = dyn_cast<CallBase>(QueryInst)) {
> bool isReadOnly = AA.onlyReadsMemory(QueryCall);
> LocalCache = getCallDependencyFrom(QueryCall, isReadOnly,
>
> diff --git a/llvm/lib/Analysis/OrderedBasicBlock.cpp b/llvm/lib/Analysis/OrderedBasicBlock.cpp
> deleted file mode 100644
> index 48f2a4020c66..000000000000
> --- a/llvm/lib/Analysis/OrderedBasicBlock.cpp
> +++ /dev/null
> @@ -1,111 +0,0 @@
> -//===- OrderedBasicBlock.cpp --------------------------------- -*- 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 implements the OrderedBasicBlock class. OrderedBasicBlock
> -// maintains an interface where clients can query if one instruction comes
> -// before another in a BasicBlock. Since BasicBlock currently lacks a reliable
> -// way to query relative position between instructions one can use
> -// OrderedBasicBlock to do such queries. OrderedBasicBlock is lazily built on a
> -// source BasicBlock and maintains an internal Instruction -> Position map. A
> -// OrderedBasicBlock instance should be discarded whenever the source
> -// BasicBlock changes.
> -//
> -// It's currently used by the CaptureTracker in order to find relative
> -// positions of a pair of instructions inside a BasicBlock.
> -//
> -//===----------------------------------------------------------------------===//
> -
> -#include "llvm/Analysis/OrderedBasicBlock.h"
> -#include "llvm/IR/Instruction.h"
> -using namespace llvm;
> -
> -OrderedBasicBlock::OrderedBasicBlock(const BasicBlock *BasicB)
> - : NextInstPos(0), BB(BasicB) {
> - LastInstFound = BB->end();
> -}
> -
> -/// Given no cached results, find if \p A comes before \p B in \p BB.
> -/// Cache and number out instruction while walking \p BB.
> -bool OrderedBasicBlock::comesBefore(const Instruction *A,
> - const Instruction *B) {
> - const Instruction *Inst = nullptr;
> - assert(!(LastInstFound == BB->end() && NextInstPos != 0) &&
> - "Instruction supposed to be in NumberedInsts");
> - assert(A->getParent() == BB && "Instruction supposed to be in the block!");
> - assert(B->getParent() == BB && "Instruction supposed to be in the block!");
> -
> - // Start the search with the instruction found in the last lookup round.
> - auto II = BB->begin();
> - auto IE = BB->end();
> - if (LastInstFound != IE)
> - II = std::next(LastInstFound);
> -
> - // Number all instructions up to the point where we find 'A' or 'B'.
> - for (; II != IE; ++II) {
> - Inst = cast<Instruction>(II);
> - NumberedInsts[Inst] = NextInstPos++;
> - if (Inst == A || Inst == B)
> - break;
> - }
> -
> - assert(II != IE && "Instruction not found?");
> - assert((Inst == A || Inst == B) && "Should find A or B");
> - LastInstFound = II;
> - return Inst != B;
> -}
> -
> -/// Find out whether \p A dominates \p B, meaning whether \p A
> -/// comes before \p B in \p BB. This is a simplification that considers
> -/// cached instruction positions and ignores other basic blocks, being
> -/// only relevant to compare relative instructions positions inside \p BB.
> -bool OrderedBasicBlock::dominates(const Instruction *A, const Instruction *B) {
> - assert(A->getParent() == B->getParent() &&
> - "Instructions must be in the same basic block!");
> - assert(A->getParent() == BB && "Instructions must be in the tracked block!");
> -
> - // First we lookup the instructions. If they don't exist, lookup will give us
> - // back ::end(). If they both exist, we compare the numbers. Otherwise, if NA
> - // exists and NB doesn't, it means NA must come before NB because we would
> - // have numbered NB as well if it didn't. The same is true for NB. If it
> - // exists, but NA does not, NA must come after it. If neither exist, we need
> - // to number the block and cache the results (by calling comesBefore).
> - auto NAI = NumberedInsts.find(A);
> - auto NBI = NumberedInsts.find(B);
> - if (NAI != NumberedInsts.end() && NBI != NumberedInsts.end())
> - return NAI->second < NBI->second;
> - if (NAI != NumberedInsts.end())
> - return true;
> - if (NBI != NumberedInsts.end())
> - return false;
> -
> - return comesBefore(A, B);
> -}
> -
> -void OrderedBasicBlock::eraseInstruction(const Instruction *I) {
> - if (LastInstFound != BB->end() && I == &*LastInstFound) {
> - if (LastInstFound == BB->begin()) {
> - LastInstFound = BB->end();
> - NextInstPos = 0;
> - } else
> - LastInstFound--;
> - }
> -
> - NumberedInsts.erase(I);
> -}
> -
> -void OrderedBasicBlock::replaceInstruction(const Instruction *Old,
> - const Instruction *New) {
> - auto OI = NumberedInsts.find(Old);
> - if (OI == NumberedInsts.end())
> - return;
> -
> - NumberedInsts.insert({New, OI->second});
> - if (LastInstFound != BB->end() && Old == &*LastInstFound)
> - LastInstFound = New->getIterator();
> - NumberedInsts.erase(Old);
> -}
>
> diff --git a/llvm/lib/Analysis/OrderedInstructions.cpp b/llvm/lib/Analysis/OrderedInstructions.cpp
> index e947e5e388a8..11ab3e0927d2 100644
> --- a/llvm/lib/Analysis/OrderedInstructions.cpp
> +++ b/llvm/lib/Analysis/OrderedInstructions.cpp
> @@ -18,16 +18,11 @@ bool OrderedInstructions::localDominates(const Instruction *InstA,
> assert(InstA->getParent() == InstB->getParent() &&
> "Instructions must be in the same basic block");
>
> - const BasicBlock *IBB = InstA->getParent();
> - auto OBB = OBBMap.find(IBB);
> - if (OBB == OBBMap.end())
> - OBB = OBBMap.insert({IBB, std::make_unique<OrderedBasicBlock>(IBB)}).first;
> - return OBB->second->dominates(InstA, InstB);
> + return InstA->comesBefore(InstB);
> }
>
> -/// Given 2 instructions, use OrderedBasicBlock to check for dominance relation
> -/// if the instructions are in the same basic block, Otherwise, use dominator
> -/// tree.
> +/// Given 2 instructions, check for dominance relation if the instructions are
> +/// in the same basic block. Otherwise, use dominator tree.
> bool OrderedInstructions::dominates(const Instruction *InstA,
> const Instruction *InstB) const {
> // Use ordered basic block to do dominance check in case the 2 instructions
>
> diff --git a/llvm/lib/IR/BasicBlock.cpp b/llvm/lib/IR/BasicBlock.cpp
> index d9a9536b3b6a..679c72fd3dd7 100644
> --- a/llvm/lib/IR/BasicBlock.cpp
> +++ b/llvm/lib/IR/BasicBlock.cpp
> @@ -33,6 +33,10 @@ LLVMContext &BasicBlock::getContext() const {
> return getType()->getContext();
> }
>
> +template <> void llvm::invalidateParentIListOrdering(BasicBlock *BB) {
> + BB->invalidateOrders();
> +}
> +
> // Explicit instantiation of SymbolTableListTraits since some of the methods
> // are not in the public header file...
> template class llvm::SymbolTableListTraits<Instruction>;
> @@ -61,6 +65,8 @@ void BasicBlock::insertInto(Function *NewParent, BasicBlock *InsertBefore) {
> }
>
> BasicBlock::~BasicBlock() {
> + validateInstrOrdering();
> +
> // If the address of the block is taken and it is being deleted (e.g. because
> // it is dead), this means that there is either a dangling constant expr
> // hanging off the block, or an undefined use of the block (source code
> @@ -506,3 +512,29 @@ BasicBlock::iterator llvm::skipDebugIntrinsics(BasicBlock::iterator It) {
> ++It;
> return It;
> }
> +
> +void BasicBlock::renumberInstructions() {
> + unsigned Order = 0;
> + for (Instruction &I : *this)
> + I.Order = Order++;
> +
> + // Set the bit to indicate that the instruction order valid and cached.
> + BasicBlockBits Bits = getBasicBlockBits();
> + Bits.InstrOrderValid = true;
> + setBasicBlockBits(Bits);
> +}
> +
> +#ifndef NDEBUG
> +/// In asserts builds, this checks the numbering. In non-asserts builds, it
> +/// is defined as an inline function returning true in BasicBlock.h.
> +void BasicBlock::validateInstrOrdering() const {
> + if (!isInstrOrderValid())
> + return;
> + const Instruction *Prev = nullptr;
> + for (const Instruction &I : *this) {
> + assert((!Prev || Prev->comesBefore(&I)) &&
> + "cached instruction ordering is incorrect");
> + Prev = &I;
> + }
> +}
> +#endif
>
> diff --git a/llvm/lib/IR/Instruction.cpp b/llvm/lib/IR/Instruction.cpp
> index 7da169712896..2ef109067dd6 100644
> --- a/llvm/lib/IR/Instruction.cpp
> +++ b/llvm/lib/IR/Instruction.cpp
> @@ -97,6 +97,15 @@ void Instruction::moveBefore(BasicBlock &BB,
> BB.getInstList().splice(I, getParent()->getInstList(), getIterator());
> }
>
> +bool Instruction::comesBefore(const Instruction *Other) const {
> + assert(Parent && Other->Parent &&
> + "instructions without BB parents have no order");
> + assert(Parent == Other->Parent && "cross-BB instruction order comparison");
> + if (!Parent->isInstrOrderValid())
> + Parent->renumberInstructions();
> + return Order < Other->Order;
> +}
> +
> void Instruction::setHasNoUnsignedWrap(bool b) {
> cast<OverflowingBinaryOperator>(this)->setHasNoUnsignedWrap(b);
> }
>
> diff --git a/llvm/lib/IR/SymbolTableListTraitsImpl.h b/llvm/lib/IR/SymbolTableListTraitsImpl.h
> index f399c823d6fb..4283744bd058 100644
> --- a/llvm/lib/IR/SymbolTableListTraitsImpl.h
> +++ b/llvm/lib/IR/SymbolTableListTraitsImpl.h
> @@ -20,6 +20,11 @@
>
> namespace llvm {
>
> +/// Notify basic blocks when an instruction is inserted.
> +template <typename ParentClass>
> +inline void invalidateParentIListOrdering(ParentClass *Parent) {}
> +template <> void invalidateParentIListOrdering(BasicBlock *BB);
> +
> /// setSymTabObject - This is called when (f.e.) the parent of a basic block
> /// changes. This requires us to remove all the instruction symtab entries from
> /// the current function and reinsert them into the new function.
> @@ -64,6 +69,7 @@ void SymbolTableListTraits<ValueSubClass>::addNodeToList(ValueSubClass *V) {
> assert(!V->getParent() && "Value already in a container!!");
> ItemParentClass *Owner = getListOwner();
> V->setParent(Owner);
> + invalidateParentIListOrdering(Owner);
> if (V->hasName())
> if (ValueSymbolTable *ST = getSymTab(Owner))
> ST->reinsertValue(V);
> @@ -81,8 +87,13 @@ void SymbolTableListTraits<ValueSubClass>::removeNodeFromList(
> template <typename ValueSubClass>
> void SymbolTableListTraits<ValueSubClass>::transferNodesFromList(
> SymbolTableListTraits &L2, iterator first, iterator last) {
> - // We only have to do work here if transferring instructions between BBs
> - ItemParentClass *NewIP = getListOwner(), *OldIP = L2.getListOwner();
> + // Transfering nodes, even within the same BB, invalidates the ordering. The
> + // list that we removed the nodes from still has a valid ordering.
> + ItemParentClass *NewIP = getListOwner();
> + invalidateParentIListOrdering(NewIP);
> +
> + // Nothing else needs to be done if we're reording nodes within the same list.
> + ItemParentClass *OldIP = L2.getListOwner();
> if (NewIP == OldIP)
> return;
>
>
> diff --git a/llvm/lib/Target/ARM/ARMParallelDSP.cpp b/llvm/lib/Target/ARM/ARMParallelDSP.cpp
> index 51d22d2bfe74..bf90abc2a0e3 100644
> --- a/llvm/lib/Target/ARM/ARMParallelDSP.cpp
> +++ b/llvm/lib/Target/ARM/ARMParallelDSP.cpp
> @@ -20,7 +20,6 @@
> #include "llvm/ADT/Statistic.h"
> #include "llvm/Analysis/AliasAnalysis.h"
> #include "llvm/Analysis/LoopAccessAnalysis.h"
> -#include "llvm/Analysis/OrderedBasicBlock.h"
> #include "llvm/CodeGen/TargetPassConfig.h"
> #include "llvm/IR/Instructions.h"
> #include "llvm/IR/IntrinsicsARM.h"
> @@ -352,7 +351,6 @@ bool ARMParallelDSP::RecordMemoryOps(BasicBlock *BB) {
> SmallVector<Instruction*, 8> Writes;
> LoadPairs.clear();
> WideLoads.clear();
> - OrderedBasicBlock OrderedBB(BB);
>
> // Collect loads and instruction that may write to memory. For now we only
> // record loads which are simple, sign-extended and have a single user.
> @@ -384,7 +382,7 @@ bool ARMParallelDSP::RecordMemoryOps(BasicBlock *BB) {
> if (!isModOrRefSet(intersectModRef(AA->getModRefInfo(Write, ReadLoc),
> ModRefInfo::ModRef)))
> continue;
> - if (OrderedBB.dominates(Write, Read))
> + if (Write->comesBefore(Read))
> RAWDeps[Read].insert(Write);
> }
> }
> @@ -392,8 +390,9 @@ bool ARMParallelDSP::RecordMemoryOps(BasicBlock *BB) {
> // Check whether there's not a write between the two loads which would
> // prevent them from being safely merged.
> auto SafeToPair = [&](LoadInst *Base, LoadInst *Offset) {
> - LoadInst *Dominator = OrderedBB.dominates(Base, Offset) ? Base : Offset;
> - LoadInst *Dominated = OrderedBB.dominates(Base, Offset) ? Offset : Base;
> + bool BaseFirst = Base->comesBefore(Offset);
> + LoadInst *Dominator = BaseFirst ? Base : Offset;
> + LoadInst *Dominated = BaseFirst ? Offset : Base;
>
> if (RAWDeps.count(Dominated)) {
> InstSet &WritesBefore = RAWDeps[Dominated];
> @@ -401,7 +400,7 @@ bool ARMParallelDSP::RecordMemoryOps(BasicBlock *BB) {
> for (auto Before : WritesBefore) {
> // We can't move the second load backward, past a write, to merge
> // with the first load.
> - if (OrderedBB.dominates(Dominator, Before))
> + if (Dominator->comesBefore(Before))
> return false;
> }
> }
> @@ -705,12 +704,11 @@ void ARMParallelDSP::InsertParallelMACs(Reduction &R) {
> }
>
> // Roughly sort the mul pairs in their program order.
> - OrderedBasicBlock OrderedBB(R.getRoot()->getParent());
> - llvm::sort(R.getMulPairs(), [&OrderedBB](auto &PairA, auto &PairB) {
> - const Instruction *A = PairA.first->Root;
> - const Instruction *B = PairB.first->Root;
> - return OrderedBB.dominates(A, B);
> - });
> + llvm::sort(R.getMulPairs(), [](auto &PairA, auto &PairB) {
> + const Instruction *A = PairA.first->Root;
> + const Instruction *B = PairB.first->Root;
> + return A->comesBefore(B);
> + });
>
> IntegerType *Ty = IntegerType::get(M->getContext(), 32);
> for (auto &Pair : R.getMulPairs()) {
>
> diff --git a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
> index 7106fb086723..6c5ca5bbe1e9 100644
> --- a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
> +++ b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
> @@ -31,7 +31,6 @@
> #include "llvm/Analysis/MemoryLocation.h"
> #include "llvm/Analysis/MemorySSA.h"
> #include "llvm/Analysis/MemorySSAUpdater.h"
> -#include "llvm/Analysis/OrderedBasicBlock.h"
> #include "llvm/Analysis/PostDominators.h"
> #include "llvm/Analysis/TargetLibraryInfo.h"
> #include "llvm/Analysis/ValueTracking.h"
> @@ -118,7 +117,7 @@ using InstOverlapIntervalsTy = DenseMap<Instruction *, OverlapIntervalsTy>;
> static void
> deleteDeadInstruction(Instruction *I, BasicBlock::iterator *BBI,
> MemoryDependenceResults &MD, const TargetLibraryInfo &TLI,
> - InstOverlapIntervalsTy &IOL, OrderedBasicBlock &OBB,
> + InstOverlapIntervalsTy &IOL,
> MapVector<Instruction *, bool> &ThrowableInst,
> SmallSetVector<const Value *, 16> *ValueSet = nullptr) {
> SmallVector<Instruction*, 32> NowDeadInsts;
> @@ -161,7 +160,6 @@ deleteDeadInstruction(Instruction *I, BasicBlock::iterator *BBI,
>
> if (ValueSet) ValueSet->remove(DeadInst);
> IOL.erase(DeadInst);
> - OBB.eraseInstruction(DeadInst);
>
> if (NewIter == DeadInst->getIterator())
> NewIter = DeadInst->eraseFromParent();
> @@ -687,7 +685,7 @@ static void findUnconditionalPreds(SmallVectorImpl<BasicBlock *> &Blocks,
> static bool handleFree(CallInst *F, AliasAnalysis *AA,
> MemoryDependenceResults *MD, DominatorTree *DT,
> const TargetLibraryInfo *TLI,
> - InstOverlapIntervalsTy &IOL, OrderedBasicBlock &OBB,
> + InstOverlapIntervalsTy &IOL,
> MapVector<Instruction *, bool> &ThrowableInst) {
> bool MadeChange = false;
>
> @@ -722,7 +720,7 @@ static bool handleFree(CallInst *F, AliasAnalysis *AA,
>
> // DCE instructions only used to calculate that store.
> BasicBlock::iterator BBI(Dependency);
> - deleteDeadInstruction(Dependency, &BBI, *MD, *TLI, IOL, OBB,
> + deleteDeadInstruction(Dependency, &BBI, *MD, *TLI, IOL,
> ThrowableInst);
> ++NumFastStores;
> MadeChange = true;
> @@ -780,7 +778,7 @@ static void removeAccessedObjects(const MemoryLocation &LoadedLoc,
> static bool handleEndBlock(BasicBlock &BB, AliasAnalysis *AA,
> MemoryDependenceResults *MD,
> const TargetLibraryInfo *TLI,
> - InstOverlapIntervalsTy &IOL, OrderedBasicBlock &OBB,
> + InstOverlapIntervalsTy &IOL,
> MapVector<Instruction *, bool> &ThrowableInst) {
> bool MadeChange = false;
>
> @@ -842,7 +840,7 @@ static bool handleEndBlock(BasicBlock &BB, AliasAnalysis *AA,
> << '\n');
>
> // DCE instructions only used to calculate that store.
> - deleteDeadInstruction(Dead, &BBI, *MD, *TLI, IOL, OBB, ThrowableInst,
> + deleteDeadInstruction(Dead, &BBI, *MD, *TLI, IOL, ThrowableInst,
> &DeadStackObjects);
> ++NumFastStores;
> MadeChange = true;
> @@ -854,7 +852,7 @@ static bool handleEndBlock(BasicBlock &BB, AliasAnalysis *AA,
> if (isInstructionTriviallyDead(&*BBI, TLI)) {
> LLVM_DEBUG(dbgs() << "DSE: Removing trivially dead instruction:\n DEAD: "
> << *&*BBI << '\n');
> - deleteDeadInstruction(&*BBI, &BBI, *MD, *TLI, IOL, OBB, ThrowableInst,
> + deleteDeadInstruction(&*BBI, &BBI, *MD, *TLI, IOL, ThrowableInst,
> &DeadStackObjects);
> ++NumFastOther;
> MadeChange = true;
> @@ -1061,7 +1059,6 @@ static bool eliminateNoopStore(Instruction *Inst, BasicBlock::iterator &BBI,
> const DataLayout &DL,
> const TargetLibraryInfo *TLI,
> InstOverlapIntervalsTy &IOL,
> - OrderedBasicBlock &OBB,
> MapVector<Instruction *, bool> &ThrowableInst) {
> // Must be a store instruction.
> StoreInst *SI = dyn_cast<StoreInst>(Inst);
> @@ -1078,7 +1075,7 @@ static bool eliminateNoopStore(Instruction *Inst, BasicBlock::iterator &BBI,
> dbgs() << "DSE: Remove Store Of Load from same pointer:\n LOAD: "
> << *DepLoad << "\n STORE: " << *SI << '\n');
>
> - deleteDeadInstruction(SI, &BBI, *MD, *TLI, IOL, OBB, ThrowableInst);
> + deleteDeadInstruction(SI, &BBI, *MD, *TLI, IOL, ThrowableInst);
> ++NumRedundantStores;
> return true;
> }
> @@ -1096,7 +1093,7 @@ static bool eliminateNoopStore(Instruction *Inst, BasicBlock::iterator &BBI,
> dbgs() << "DSE: Remove null store to the calloc'ed object:\n DEAD: "
> << *Inst << "\n OBJECT: " << *UnderlyingPointer << '\n');
>
> - deleteDeadInstruction(SI, &BBI, *MD, *TLI, IOL, OBB, ThrowableInst);
> + deleteDeadInstruction(SI, &BBI, *MD, *TLI, IOL, ThrowableInst);
> ++NumRedundantStores;
> return true;
> }
> @@ -1110,7 +1107,6 @@ static bool eliminateDeadStores(BasicBlock &BB, AliasAnalysis *AA,
> const DataLayout &DL = BB.getModule()->getDataLayout();
> bool MadeChange = false;
>
> - OrderedBasicBlock OBB(&BB);
> MapVector<Instruction *, bool> ThrowableInst;
>
> // A map of interval maps representing partially-overwritten value parts.
> @@ -1120,7 +1116,7 @@ static bool eliminateDeadStores(BasicBlock &BB, AliasAnalysis *AA,
> for (BasicBlock::iterator BBI = BB.begin(), BBE = BB.end(); BBI != BBE; ) {
> // Handle 'free' calls specially.
> if (CallInst *F = isFreeCall(&*BBI, TLI)) {
> - MadeChange |= handleFree(F, AA, MD, DT, TLI, IOL, OBB, ThrowableInst);
> + MadeChange |= handleFree(F, AA, MD, DT, TLI, IOL, ThrowableInst);
> // Increment BBI after handleFree has potentially deleted instructions.
> // This ensures we maintain a valid iterator.
> ++BBI;
> @@ -1139,14 +1135,14 @@ static bool eliminateDeadStores(BasicBlock &BB, AliasAnalysis *AA,
> continue;
>
> // eliminateNoopStore will update in iterator, if necessary.
> - if (eliminateNoopStore(Inst, BBI, AA, MD, DL, TLI, IOL, OBB,
> + if (eliminateNoopStore(Inst, BBI, AA, MD, DL, TLI, IOL,
> ThrowableInst)) {
> MadeChange = true;
> continue;
> }
>
> // If we find something that writes memory, get its memory dependence.
> - MemDepResult InstDep = MD->getDependency(Inst, &OBB);
> + MemDepResult InstDep = MD->getDependency(Inst);
>
> // Ignore any store where we can't find a local dependence.
> // FIXME: cross-block DSE would be fun. :)
> @@ -1197,7 +1193,7 @@ static bool eliminateDeadStores(BasicBlock &BB, AliasAnalysis *AA,
> // If the underlying object is a non-escaping memory allocation, any store
> // to it is dead along the unwind edge. Otherwise, we need to preserve
> // the store.
> - if (LastThrowing && OBB.dominates(DepWrite, LastThrowing)) {
> + if (LastThrowing && DepWrite->comesBefore(LastThrowing)) {
> const Value* Underlying = GetUnderlyingObject(DepLoc.Ptr, DL);
> bool IsStoreDeadOnUnwind = isa<AllocaInst>(Underlying);
> if (!IsStoreDeadOnUnwind) {
> @@ -1228,13 +1224,13 @@ static bool eliminateDeadStores(BasicBlock &BB, AliasAnalysis *AA,
> << "\n KILLER: " << *Inst << '\n');
>
> // Delete the store and now-dead instructions that feed it.
> - deleteDeadInstruction(DepWrite, &BBI, *MD, *TLI, IOL, OBB,
> + deleteDeadInstruction(DepWrite, &BBI, *MD, *TLI, IOL,
> ThrowableInst);
> ++NumFastStores;
> MadeChange = true;
>
> // We erased DepWrite; start over.
> - InstDep = MD->getDependency(Inst, &OBB);
> + InstDep = MD->getDependency(Inst);
> continue;
> } else if ((OR == OW_End && isShortenableAtTheEnd(DepWrite)) ||
> ((OR == OW_Begin &&
> @@ -1307,13 +1303,10 @@ static bool eliminateDeadStores(BasicBlock &BB, AliasAnalysis *AA,
> SI->copyMetadata(*DepWrite, MDToKeep);
> ++NumModifiedStores;
>
> - // Remove earlier, wider, store
> - OBB.replaceInstruction(DepWrite, SI);
> -
> // Delete the old stores and now-dead instructions that feed them.
> - deleteDeadInstruction(Inst, &BBI, *MD, *TLI, IOL, OBB,
> + deleteDeadInstruction(Inst, &BBI, *MD, *TLI, IOL,
> ThrowableInst);
> - deleteDeadInstruction(DepWrite, &BBI, *MD, *TLI, IOL, OBB,
> + deleteDeadInstruction(DepWrite, &BBI, *MD, *TLI, IOL,
> ThrowableInst);
> MadeChange = true;
>
> @@ -1349,7 +1342,7 @@ static bool eliminateDeadStores(BasicBlock &BB, AliasAnalysis *AA,
> // If this block ends in a return, unwind, or unreachable, all allocas are
> // dead at its end, which means stores to them are also dead.
> if (BB.getTerminator()->getNumSuccessors() == 0)
> - MadeChange |= handleEndBlock(BB, AA, MD, TLI, IOL, OBB, ThrowableInst);
> + MadeChange |= handleEndBlock(BB, AA, MD, TLI, IOL, ThrowableInst);
>
> return MadeChange;
> }
>
> diff --git a/llvm/lib/Transforms/Vectorize/LoadStoreVectorizer.cpp b/llvm/lib/Transforms/Vectorize/LoadStoreVectorizer.cpp
> index 8ab03c34335d..b0c1a296aace 100644
> --- a/llvm/lib/Transforms/Vectorize/LoadStoreVectorizer.cpp
> +++ b/llvm/lib/Transforms/Vectorize/LoadStoreVectorizer.cpp
> @@ -50,7 +50,6 @@
> #include "llvm/ADT/iterator_range.h"
> #include "llvm/Analysis/AliasAnalysis.h"
> #include "llvm/Analysis/MemoryLocation.h"
> -#include "llvm/Analysis/OrderedBasicBlock.h"
> #include "llvm/Analysis/ScalarEvolution.h"
> #include "llvm/Analysis/TargetTransformInfo.h"
> #include "llvm/Analysis/ValueTracking.h"
> @@ -502,7 +501,6 @@ bool Vectorizer::lookThroughSelects(Value *PtrA, Value *PtrB,
> }
>
> void Vectorizer::reorder(Instruction *I) {
> - OrderedBasicBlock OBB(I->getParent());
> SmallPtrSet<Instruction *, 16> InstructionsToMove;
> SmallVector<Instruction *, 16> Worklist;
>
> @@ -520,7 +518,7 @@ void Vectorizer::reorder(Instruction *I) {
> if (IM->getParent() != I->getParent())
> continue;
>
> - if (!OBB.dominates(IM, I)) {
> + if (!IM->comesBefore(I)) {
> InstructionsToMove.insert(IM);
> Worklist.push_back(IM);
> }
> @@ -636,8 +634,6 @@ Vectorizer::getVectorizablePrefix(ArrayRef<Instruction *> Chain) {
> }
> }
>
> - OrderedBasicBlock OBB(Chain[0]->getParent());
> -
> // Loop until we find an instruction in ChainInstrs that we can't vectorize.
> unsigned ChainInstrIdx = 0;
> Instruction *BarrierMemoryInstr = nullptr;
> @@ -647,14 +643,14 @@ Vectorizer::getVectorizablePrefix(ArrayRef<Instruction *> Chain) {
>
> // If a barrier memory instruction was found, chain instructions that follow
> // will not be added to the valid prefix.
> - if (BarrierMemoryInstr && OBB.dominates(BarrierMemoryInstr, ChainInstr))
> + if (BarrierMemoryInstr && BarrierMemoryInstr->comesBefore(ChainInstr))
> break;
>
> // Check (in BB order) if any instruction prevents ChainInstr from being
> // vectorized. Find and store the first such "conflicting" instruction.
> for (Instruction *MemInstr : MemoryInstrs) {
> // If a barrier memory instruction was found, do not check past it.
> - if (BarrierMemoryInstr && OBB.dominates(BarrierMemoryInstr, MemInstr))
> + if (BarrierMemoryInstr && BarrierMemoryInstr->comesBefore(MemInstr))
> break;
>
> auto *MemLoad = dyn_cast<LoadInst>(MemInstr);
> @@ -673,12 +669,12 @@ Vectorizer::getVectorizablePrefix(ArrayRef<Instruction *> Chain) {
> // vectorize it (the vectorized load is inserted at the location of the
> // first load in the chain).
> if (isa<StoreInst>(MemInstr) && ChainLoad &&
> - (IsInvariantLoad(ChainLoad) || OBB.dominates(ChainLoad, MemInstr)))
> + (IsInvariantLoad(ChainLoad) || ChainLoad->comesBefore(MemInstr)))
> continue;
>
> // Same case, but in reverse.
> if (MemLoad && isa<StoreInst>(ChainInstr) &&
> - (IsInvariantLoad(MemLoad) || OBB.dominates(MemLoad, ChainInstr)))
> + (IsInvariantLoad(MemLoad) || MemLoad->comesBefore(ChainInstr)))
> continue;
>
> if (!AA.isNoAlias(MemoryLocation::get(MemInstr),
> @@ -704,7 +700,7 @@ Vectorizer::getVectorizablePrefix(ArrayRef<Instruction *> Chain) {
> // the basic block.
> if (IsLoadChain && BarrierMemoryInstr) {
> // The BarrierMemoryInstr is a store that precedes ChainInstr.
> - assert(OBB.dominates(BarrierMemoryInstr, ChainInstr));
> + assert(BarrierMemoryInstr->comesBefore(ChainInstr));
> break;
> }
> }
>
> diff --git a/llvm/unittests/Analysis/CMakeLists.txt b/llvm/unittests/Analysis/CMakeLists.txt
> index 3a631d446691..d66dd39c6013 100644
> --- a/llvm/unittests/Analysis/CMakeLists.txt
> +++ b/llvm/unittests/Analysis/CMakeLists.txt
> @@ -25,7 +25,6 @@ add_llvm_unittest(AnalysisTests
> LoopInfoTest.cpp
> MemoryBuiltinsTest.cpp
> MemorySSATest.cpp
> - OrderedBasicBlockTest.cpp
> OrderedInstructionsTest.cpp
> PhiValuesTest.cpp
> ProfileSummaryInfoTest.cpp
>
> diff --git a/llvm/unittests/Analysis/CaptureTrackingTest.cpp b/llvm/unittests/Analysis/CaptureTrackingTest.cpp
> index 86a0aa16a066..e4c8a9ff0f74 100644
> --- a/llvm/unittests/Analysis/CaptureTrackingTest.cpp
> +++ b/llvm/unittests/Analysis/CaptureTrackingTest.cpp
> @@ -7,7 +7,6 @@
> //===----------------------------------------------------------------------===//
>
> #include "llvm/Analysis/CaptureTracking.h"
> -#include "llvm/Analysis/OrderedBasicBlock.h"
> #include "llvm/AsmParser/Parser.h"
> #include "llvm/IR/Dominators.h"
> #include "llvm/IR/Instructions.h"
> @@ -62,14 +61,13 @@ TEST(CaptureTracking, MaxUsesToExplore) {
>
> BasicBlock *EntryBB = &F->getEntryBlock();
> DominatorTree DT(*F);
> - OrderedBasicBlock OBB(EntryBB);
>
> Instruction *Ret = EntryBB->getTerminator();
> ASSERT_TRUE(isa<ReturnInst>(Ret));
> - ASSERT_FALSE(PointerMayBeCapturedBefore(Arg, true, true, Ret, &DT, false,
> - &OBB, FalseMaxUsesLimit));
> + ASSERT_FALSE(PointerMayBeCapturedBefore(Arg, true, true, Ret, &DT, false,
> + FalseMaxUsesLimit));
> ASSERT_TRUE(PointerMayBeCapturedBefore(Arg, true, true, Ret, &DT, false,
> - &OBB, TrueMaxUsesLimit));
> + TrueMaxUsesLimit));
> };
>
> Test("test_few_uses", 6, 4);
>
> diff --git a/llvm/unittests/Analysis/OrderedBasicBlockTest.cpp b/llvm/unittests/Analysis/OrderedBasicBlockTest.cpp
> deleted file mode 100644
> index 4cccb38daff3..000000000000
> --- a/llvm/unittests/Analysis/OrderedBasicBlockTest.cpp
> +++ /dev/null
> @@ -1,57 +0,0 @@
> -//===- OrderedBasicBlockTest.cpp - OrderedBasicBlock unit tests -----------===//
> -//
> -// 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
> -//
> -//===----------------------------------------------------------------------===//
> -
> -#include "llvm/Analysis/OrderedBasicBlock.h"
> -#include "llvm/AsmParser/Parser.h"
> -#include "llvm/IR/BasicBlock.h"
> -#include "llvm/IR/Function.h"
> -#include "llvm/IR/LLVMContext.h"
> -#include "llvm/IR/Module.h"
> -#include "llvm/Support/DataTypes.h"
> -#include "llvm/Support/SourceMgr.h"
> -#include "gtest/gtest.h"
> -
> -namespace llvm {
> -namespace {
> -
> -class OrderedBasicBlockTest : public testing::Test {
> -protected:
> - LLVMContext C;
> -
> - std::unique_ptr<Module> makeLLVMModule() {
> - const char *ModuleString = R"(define i32 @f(i32 %x) {
> - %add = add i32 %x, 42
> - ret i32 %add
> - })";
> - SMDiagnostic Err;
> - auto foo = parseAssemblyString(ModuleString, Err, C);
> - return foo;
> - }
> -};
> -
> -TEST_F(OrderedBasicBlockTest, Basic) {
> - auto M = makeLLVMModule();
> - Function *F = M->getFunction("f");
> - BasicBlock::iterator I = F->front().begin();
> - Instruction *Add = &*I++;
> - Instruction *Ret = &*I++;
> -
> - OrderedBasicBlock OBB(&F->front());
> - // Intentionally duplicated to verify cached and uncached are the same.
> - EXPECT_FALSE(OBB.dominates(Add, Add));
> - EXPECT_FALSE(OBB.dominates(Add, Add));
> - EXPECT_TRUE(OBB.dominates(Add, Ret));
> - EXPECT_TRUE(OBB.dominates(Add, Ret));
> - EXPECT_FALSE(OBB.dominates(Ret, Add));
> - EXPECT_FALSE(OBB.dominates(Ret, Add));
> - EXPECT_FALSE(OBB.dominates(Ret, Ret));
> - EXPECT_FALSE(OBB.dominates(Ret, Ret));
> -}
> -
> -} // end anonymous namespace
> -} // end namespace llvm
>
> diff --git a/llvm/unittests/IR/BasicBlockTest.cpp b/llvm/unittests/IR/BasicBlockTest.cpp
> index ad446ee6ebab..fcdc9c2c07fb 100644
> --- a/llvm/unittests/IR/BasicBlockTest.cpp
> +++ b/llvm/unittests/IR/BasicBlockTest.cpp
> @@ -8,11 +8,13 @@
>
> #include "llvm/IR/BasicBlock.h"
> #include "llvm/ADT/STLExtras.h"
> +#include "llvm/AsmParser/Parser.h"
> #include "llvm/IR/Function.h"
> #include "llvm/IR/IRBuilder.h"
> #include "llvm/IR/LLVMContext.h"
> #include "llvm/IR/Module.h"
> #include "llvm/IR/NoFolder.h"
> +#include "llvm/Support/SourceMgr.h"
> #include "gmock/gmock-matchers.h"
> #include "gtest/gtest.h"
> #include <memory>
> @@ -129,5 +131,130 @@ TEST(BasicBlockTest, TestInstructionsWithoutDebug) {
> delete V;
> }
>
> +TEST(BasicBlockTest, ComesBefore) {
> + const char *ModuleString = R"(define i32 @f(i32 %x) {
> + %add = add i32 %x, 42
> + ret i32 %add
> + })";
> + LLVMContext Ctx;
> + SMDiagnostic Err;
> + auto M = parseAssemblyString(ModuleString, Err, Ctx);
> + ASSERT_TRUE(M.get());
> +
> + Function *F = M->getFunction("f");
> + BasicBlock &BB = F->front();
> + BasicBlock::iterator I = BB.begin();
> + Instruction *Add = &*I++;
> + Instruction *Ret = &*I++;
> +
> + // Intentionally duplicated to verify cached and uncached are the same.
> + EXPECT_FALSE(BB.isInstrOrderValid());
> + EXPECT_FALSE(Add->comesBefore(Add));
> + EXPECT_TRUE(BB.isInstrOrderValid());
> + EXPECT_FALSE(Add->comesBefore(Add));
> + BB.invalidateOrders();
> + EXPECT_FALSE(BB.isInstrOrderValid());
> + EXPECT_TRUE(Add->comesBefore(Ret));
> + EXPECT_TRUE(BB.isInstrOrderValid());
> + EXPECT_TRUE(Add->comesBefore(Ret));
> + BB.invalidateOrders();
> + EXPECT_FALSE(Ret->comesBefore(Add));
> + EXPECT_FALSE(Ret->comesBefore(Add));
> + BB.invalidateOrders();
> + EXPECT_FALSE(Ret->comesBefore(Ret));
> + EXPECT_FALSE(Ret->comesBefore(Ret));
> +}
> +
> +class InstrOrderInvalidationTest : public ::testing::Test {
> +protected:
> + void SetUp() override {
> + M.reset(new Module("MyModule", Ctx));
> + Nop = Intrinsic::getDeclaration(M.get(), Intrinsic::donothing);
> + FunctionType *FT = FunctionType::get(Type::getVoidTy(Ctx), {}, false);
> + Function *F = Function::Create(FT, Function::ExternalLinkage, "foo", *M);
> + BB = BasicBlock::Create(Ctx, "entry", F);
> +
> + IRBuilder<> Builder(BB);
> + I1 = Builder.CreateCall(Nop);
> + I2 = Builder.CreateCall(Nop);
> + I3 = Builder.CreateCall(Nop);
> + Ret = Builder.CreateRetVoid();
> + }
> +
> + LLVMContext Ctx;
> + std::unique_ptr<Module> M;
> + Function *Nop = nullptr;
> + BasicBlock *BB = nullptr;
> + Instruction *I1 = nullptr;
> + Instruction *I2 = nullptr;
> + Instruction *I3 = nullptr;
> + Instruction *Ret = nullptr;
> +};
> +
> +TEST_F(InstrOrderInvalidationTest, InsertInvalidation) {
> + EXPECT_FALSE(BB->isInstrOrderValid());
> + EXPECT_TRUE(I1->comesBefore(I2));
> + EXPECT_TRUE(BB->isInstrOrderValid());
> + EXPECT_TRUE(I2->comesBefore(I3));
> + EXPECT_TRUE(I3->comesBefore(Ret));
> + EXPECT_TRUE(BB->isInstrOrderValid());
> +
> + // Invalidate orders.
> + IRBuilder<> Builder(BB, I2->getIterator());
> + Instruction *I1a = Builder.CreateCall(Nop);
> + EXPECT_FALSE(BB->isInstrOrderValid());
> + EXPECT_TRUE(I1->comesBefore(I1a));
> + EXPECT_TRUE(BB->isInstrOrderValid());
> + EXPECT_TRUE(I1a->comesBefore(I2));
> + EXPECT_TRUE(I2->comesBefore(I3));
> + EXPECT_TRUE(I3->comesBefore(Ret));
> + EXPECT_TRUE(BB->isInstrOrderValid());
> +}
> +
> +TEST_F(InstrOrderInvalidationTest, SpliceInvalidation) {
> + EXPECT_TRUE(I1->comesBefore(I2));
> + EXPECT_TRUE(I2->comesBefore(I3));
> + EXPECT_TRUE(I3->comesBefore(Ret));
> + EXPECT_TRUE(BB->isInstrOrderValid());
> +
> + // Use Instruction::moveBefore, which uses splice.
> + I2->moveBefore(I1);
> + EXPECT_FALSE(BB->isInstrOrderValid());
> +
> + EXPECT_TRUE(I2->comesBefore(I1));
> + EXPECT_TRUE(I1->comesBefore(I3));
> + EXPECT_TRUE(I3->comesBefore(Ret));
> + EXPECT_TRUE(BB->isInstrOrderValid());
> +}
> +
> +TEST_F(InstrOrderInvalidationTest, RemoveNoInvalidation) {
> + // Cache the instruction order.
> + EXPECT_FALSE(BB->isInstrOrderValid());
> + EXPECT_TRUE(I1->comesBefore(I2));
> + EXPECT_TRUE(BB->isInstrOrderValid());
> +
> + // Removing does not invalidate instruction order.
> + I2->removeFromParent();
> + I2->deleteValue();
> + I2 = nullptr;
> + EXPECT_TRUE(BB->isInstrOrderValid());
> + EXPECT_TRUE(I1->comesBefore(I3));
> + EXPECT_EQ(std::next(I1->getIterator()), I3->getIterator());
> +}
> +
> +TEST_F(InstrOrderInvalidationTest, EraseNoInvalidation) {
> + // Cache the instruction order.
> + EXPECT_FALSE(BB->isInstrOrderValid());
> + EXPECT_TRUE(I1->comesBefore(I2));
> + EXPECT_TRUE(BB->isInstrOrderValid());
> +
> + // Removing does not invalidate instruction order.
> + I2->eraseFromParent();
> + I2 = nullptr;
> + EXPECT_TRUE(BB->isInstrOrderValid());
> + EXPECT_TRUE(I1->comesBefore(I3));
> + EXPECT_EQ(std::next(I1->getIterator()), I3->getIterator());
> +}
> +
> } // End anonymous namespace.
> } // End llvm namespace.
>
> diff --git a/llvm/utils/gn/secondary/llvm/lib/Analysis/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/Analysis/BUILD.gn
> index cbbe1499a560..328d819fd1f0 100644
> --- a/llvm/utils/gn/secondary/llvm/lib/Analysis/BUILD.gn
> +++ b/llvm/utils/gn/secondary/llvm/lib/Analysis/BUILD.gn
> @@ -84,7 +84,6 @@ static_library("Analysis") {
> "ObjCARCAnalysisUtils.cpp",
> "ObjCARCInstKind.cpp",
> "OptimizationRemarkEmitter.cpp",
> - "OrderedBasicBlock.cpp",
> "OrderedInstructions.cpp",
> "PHITransAddr.cpp",
> "PhiValues.cpp",
>
> diff --git a/llvm/utils/gn/secondary/llvm/unittests/Analysis/BUILD.gn b/llvm/utils/gn/secondary/llvm/unittests/Analysis/BUILD.gn
> index 726c119fd19a..47bc50212651 100644
> --- a/llvm/utils/gn/secondary/llvm/unittests/Analysis/BUILD.gn
> +++ b/llvm/utils/gn/secondary/llvm/unittests/Analysis/BUILD.gn
> @@ -27,7 +27,6 @@ unittest("AnalysisTests") {
> "LoopInfoTest.cpp",
> "MemoryBuiltinsTest.cpp",
> "MemorySSATest.cpp",
> - "OrderedBasicBlockTest.cpp",
> "OrderedInstructionsTest.cpp",
> "PhiValuesTest.cpp",
> "ProfileSummaryInfoTest.cpp",
>
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list