void reset() {
Need = false;
Pointers.clear();
+ Checks.clear();
}
/// Insert a pointer and calculate the start and end SCEVs.
SmallVector<unsigned, 2> Members;
};
- /// \brief Groups pointers such that a single memcheck is required
- /// between two different groups. This will clear the CheckingGroups vector
- /// and re-compute it. We will only group dependecies if \p UseDependencies
- /// is true, otherwise we will create a separate group for each pointer.
- void groupChecks(MemoryDepChecker::DepCandidates &DepCands,
- bool UseDependencies);
+ /// \brief A memcheck which made up of a pair of grouped pointers.
+ ///
+ /// These *have* to be const for now, since checks are generated from
+ /// CheckingPtrGroups in LAI::addRuntimeChecks which is a const member
+ /// function. FIXME: once check-generation is moved inside this class (after
+ /// the PtrPartition hack is removed), we could drop const.
+ typedef std::pair<const CheckingPtrGroup *, const CheckingPtrGroup *>
+ PointerCheck;
+
+ /// \brief Generate the checks and store it. This also performs the grouping
+ /// of pointers to reduce the number of memchecks necessary.
+ void generateChecks(MemoryDepChecker::DepCandidates &DepCands,
+ bool UseDependencies);
+
+ /// \brief Returns the checks that generateChecks created.
+ const SmallVector<PointerCheck, 4> &getChecks() const { return Checks; }
/// \brief Decide if we need to add a check between two groups of pointers,
/// according to needsChecking.
- bool needsChecking(const CheckingPtrGroup &M, const CheckingPtrGroup &N,
- const SmallVectorImpl<int> *PtrPartition) const;
-
- /// \brief Return true if any pointer requires run-time checking according
- /// to needsChecking.
- bool needsAnyChecking(const SmallVectorImpl<int> *PtrPartition) const;
+ bool needsChecking(const CheckingPtrGroup &M,
+ const CheckingPtrGroup &N) const;
/// \brief Returns the number of run-time checks required according to
/// needsChecking.
- unsigned getNumberOfChecks(const SmallVectorImpl<int> *PtrPartition) const;
+ unsigned getNumberOfChecks() const { return Checks.size(); }
/// \brief Print the list run-time memory checks necessary.
- ///
- /// If \p PtrPartition is set, it contains the partition number for
- /// pointers (-1 if the pointer belongs to multiple partitions). In this
- /// case omit checks between pointers belonging to the same partition.
- void print(raw_ostream &OS, unsigned Depth = 0,
- const SmallVectorImpl<int> *PtrPartition = nullptr) const;
+ void print(raw_ostream &OS, unsigned Depth = 0) const;
+
+ /// Print \p Checks.
+ void printChecks(raw_ostream &OS, const SmallVectorImpl<PointerCheck> &Checks,
+ unsigned Depth = 0) const;
/// This flag indicates if we need to add the runtime check.
bool Need;
/// Holds a partitioning of pointers into "check groups".
SmallVector<CheckingPtrGroup, 2> CheckingGroups;
-private:
+ /// \brief Check if pointers are in the same partition
+ ///
+ /// \p PtrToPartition contains the partition number for pointers (-1 if the
+ /// pointer belongs to multiple partitions).
+ static bool
+ arePointersInSamePartition(const SmallVectorImpl<int> &PtrToPartition,
+ unsigned PtrIdx1, unsigned PtrIdx2);
+
/// \brief Decide whether we need to issue a run-time check for pointer at
/// index \p I and \p J to prove their independence.
- ///
- /// If \p PtrPartition is set, it contains the partition number for
- /// pointers (-1 if the pointer belongs to multiple partitions). In this
- /// case omit checks between pointers belonging to the same partition.
- bool needsChecking(unsigned I, unsigned J,
- const SmallVectorImpl<int> *PtrPartition) const;
+ bool needsChecking(unsigned I, unsigned J) const;
+
+private:
+ /// \brief Groups pointers such that a single memcheck is required
+ /// between two different groups. This will clear the CheckingGroups vector
+ /// and re-compute it. We will only group dependecies if \p UseDependencies
+ /// is true, otherwise we will create a separate group for each pointer.
+ void groupChecks(MemoryDepChecker::DepCandidates &DepCands,
+ bool UseDependencies);
+
+ /// Generate the checks and return them.
+ SmallVector<PointerCheck, 4>
+ generateChecks() const;
/// Holds a pointer to the ScalarEvolution analysis.
ScalarEvolution *SE;
+
+ /// \brief Set of run-time checks required to establish independence of
+ /// otherwise may-aliasing pointers in the loop.
+ SmallVector<PointerCheck, 4> Checks;
};
/// \brief Drive the analysis of memory accesses in the loop
/// \brief Number of memchecks required to prove independence of otherwise
/// may-alias pointers.
- unsigned getNumRuntimePointerChecks(
- const SmallVectorImpl<int> *PtrPartition = nullptr) const {
- return PtrRtChecking.getNumberOfChecks(PtrPartition);
+ unsigned getNumRuntimePointerChecks() const {
+ return PtrRtChecking.getNumberOfChecks();
}
/// Return true if the block BB needs to be predicated in order for the loop
/// Returns a pair of instructions where the first element is the first
/// instruction generated in possibly a sequence of instructions and the
/// second value is the final comparator value or NULL if no check is needed.
+ std::pair<Instruction *, Instruction *>
+ addRuntimeChecks(Instruction *Loc) const;
+
+ /// \brief Generete the instructions for the checks in \p PointerChecks.
///
- /// If \p PtrPartition is set, it contains the partition number for pointers
- /// (-1 if the pointer belongs to multiple partitions). In this case omit
- /// checks between pointers belonging to the same partition.
+ /// Returns a pair of instructions where the first element is the first
+ /// instruction generated in possibly a sequence of instructions and the
+ /// second value is the final comparator value or NULL if no check is needed.
std::pair<Instruction *, Instruction *>
- addRuntimeCheck(Instruction *Loc,
- const SmallVectorImpl<int> *PtrPartition = nullptr) const;
+ addRuntimeChecks(Instruction *Loc,
+ const SmallVectorImpl<RuntimePointerChecking::PointerCheck>
+ &PointerChecks) const;
/// \brief The diagnostics report generated for the analysis. E.g. why we
/// couldn't analyze the loop.