[llvm] r177259 - Mark internal classes as POD-like to get better behavior out of

Nadav Rotem nrotem at apple.com
Tue Mar 19 21:09:59 PDT 2013


Thank you. 

On Mar 18, 2013, at 1:36 AM, Chandler Carruth <chandlerc at gmail.com> wrote:

> Author: chandlerc
> Date: Mon Mar 18 03:36:46 2013
> New Revision: 177259
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=177259&view=rev
> Log:
> Mark internal classes as POD-like to get better behavior out of
> SmallVector and DenseMap.
> 
> This speeds up SROA by 25% on PR15412.
> 
> Modified:
>    llvm/trunk/lib/Transforms/Scalar/SROA.cpp
> 
> Modified: llvm/trunk/lib/Transforms/Scalar/SROA.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/SROA.cpp?rev=177259&r1=177258&r2=177259&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Scalar/SROA.cpp (original)
> +++ llvm/trunk/lib/Transforms/Scalar/SROA.cpp Mon Mar 18 03:36:46 2013
> @@ -69,123 +69,130 @@ static cl::opt<bool>
> ForceSSAUpdater("force-ssa-updater", cl::init(false), cl::Hidden);
> 
> namespace {
> -/// \brief Alloca partitioning representation.
> -///
> -/// This class represents a partitioning of an alloca into slices, and
> -/// information about the nature of uses of each slice of the alloca. The goal
> -/// is that this information is sufficient to decide if and how to split the
> -/// alloca apart and replace slices with scalars. It is also intended that this
> -/// structure can capture the relevant information needed both to decide about
> -/// and to enact these transformations.
> -class AllocaPartitioning {
> -public:
> -  /// \brief A common base class for representing a half-open byte range.
> -  struct ByteRange {
> -    /// \brief The beginning offset of the range.
> -    uint64_t BeginOffset;
> -
> -    /// \brief The ending offset, not included in the range.
> -    uint64_t EndOffset;
> -
> -    ByteRange() : BeginOffset(), EndOffset() {}
> -    ByteRange(uint64_t BeginOffset, uint64_t EndOffset)
> -        : BeginOffset(BeginOffset), EndOffset(EndOffset) {}
> -
> -    /// \brief Support for ordering ranges.
> -    ///
> -    /// This provides an ordering over ranges such that start offsets are
> -    /// always increasing, and within equal start offsets, the end offsets are
> -    /// decreasing. Thus the spanning range comes first in a cluster with the
> -    /// same start position.
> -    bool operator<(const ByteRange &RHS) const {
> -      if (BeginOffset < RHS.BeginOffset) return true;
> -      if (BeginOffset > RHS.BeginOffset) return false;
> -      if (EndOffset > RHS.EndOffset) return true;
> -      return false;
> -    }
> -
> -    /// \brief Support comparison with a single offset to allow binary searches.
> -    friend bool operator<(const ByteRange &LHS, uint64_t RHSOffset) {
> -      return LHS.BeginOffset < RHSOffset;
> -    }
> +/// \brief A common base class for representing a half-open byte range.
> +struct ByteRange {
> +  /// \brief The beginning offset of the range.
> +  uint64_t BeginOffset;
> 
> -    friend LLVM_ATTRIBUTE_UNUSED bool operator<(uint64_t LHSOffset,
> -                                                const ByteRange &RHS) {
> -      return LHSOffset < RHS.BeginOffset;
> -    }
> +  /// \brief The ending offset, not included in the range.
> +  uint64_t EndOffset;
> 
> -    bool operator==(const ByteRange &RHS) const {
> -      return BeginOffset == RHS.BeginOffset && EndOffset == RHS.EndOffset;
> -    }
> -    bool operator!=(const ByteRange &RHS) const { return !operator==(RHS); }
> -  };
> +  ByteRange() : BeginOffset(), EndOffset() {}
> +  ByteRange(uint64_t BeginOffset, uint64_t EndOffset)
> +      : BeginOffset(BeginOffset), EndOffset(EndOffset) {}
> 
> -  /// \brief A partition of an alloca.
> +  /// \brief Support for ordering ranges.
>   ///
> -  /// This structure represents a contiguous partition of the alloca. These are
> -  /// formed by examining the uses of the alloca. During formation, they may
> -  /// overlap but once an AllocaPartitioning is built, the Partitions within it
> -  /// are all disjoint.
> -  struct Partition : public ByteRange {
> -    /// \brief Whether this partition is splittable into smaller partitions.
> -    ///
> -    /// We flag partitions as splittable when they are formed entirely due to
> -    /// accesses by trivially splittable operations such as memset and memcpy.
> -    bool IsSplittable;
> +  /// This provides an ordering over ranges such that start offsets are
> +  /// always increasing, and within equal start offsets, the end offsets are
> +  /// decreasing. Thus the spanning range comes first in a cluster with the
> +  /// same start position.
> +  bool operator<(const ByteRange &RHS) const {
> +    if (BeginOffset < RHS.BeginOffset) return true;
> +    if (BeginOffset > RHS.BeginOffset) return false;
> +    if (EndOffset > RHS.EndOffset) return true;
> +    return false;
> +  }
> 
> -    /// \brief Test whether a partition has been marked as dead.
> -    bool isDead() const {
> -      if (BeginOffset == UINT64_MAX) {
> -        assert(EndOffset == UINT64_MAX);
> -        return true;
> -      }
> -      return false;
> -    }
> +  /// \brief Support comparison with a single offset to allow binary searches.
> +  friend bool operator<(const ByteRange &LHS, uint64_t RHSOffset) {
> +    return LHS.BeginOffset < RHSOffset;
> +  }
> 
> -    /// \brief Kill a partition.
> -    /// This is accomplished by setting both its beginning and end offset to
> -    /// the maximum possible value.
> -    void kill() {
> -      assert(!isDead() && "He's Dead, Jim!");
> -      BeginOffset = EndOffset = UINT64_MAX;
> -    }
> +  friend LLVM_ATTRIBUTE_UNUSED bool operator<(uint64_t LHSOffset,
> +                                              const ByteRange &RHS) {
> +    return LHSOffset < RHS.BeginOffset;
> +  }
> 
> -    Partition() : ByteRange(), IsSplittable() {}
> -    Partition(uint64_t BeginOffset, uint64_t EndOffset, bool IsSplittable)
> -        : ByteRange(BeginOffset, EndOffset), IsSplittable(IsSplittable) {}
> -  };
> +  bool operator==(const ByteRange &RHS) const {
> +    return BeginOffset == RHS.BeginOffset && EndOffset == RHS.EndOffset;
> +  }
> +  bool operator!=(const ByteRange &RHS) const { return !operator==(RHS); }
> +};
> 
> -  /// \brief A particular use of a partition of the alloca.
> -  ///
> -  /// This structure is used to associate uses of a partition with it. They
> -  /// mark the range of bytes which are referenced by a particular instruction,
> -  /// and includes a handle to the user itself and the pointer value in use.
> -  /// The bounds of these uses are determined by intersecting the bounds of the
> -  /// memory use itself with a particular partition. As a consequence there is
> -  /// intentionally overlap between various uses of the same partition.
> -  class PartitionUse : public ByteRange {
> -    /// \brief Combined storage for both the Use* and split state.
> -    PointerIntPair<Use*, 1, bool> UsePtrAndIsSplit;
> -
> -  public:
> -    PartitionUse() : ByteRange(), UsePtrAndIsSplit() {}
> -    PartitionUse(uint64_t BeginOffset, uint64_t EndOffset, Use *U,
> -                 bool IsSplit)
> -        : ByteRange(BeginOffset, EndOffset), UsePtrAndIsSplit(U, IsSplit) {}
> -
> -    /// \brief The use in question. Provides access to both user and used value.
> -    ///
> -    /// Note that this may be null if the partition use is *dead*, that is, it
> -    /// should be ignored.
> -    Use *getUse() const { return UsePtrAndIsSplit.getPointer(); }
> +/// \brief A partition of an alloca.
> +///
> +/// This structure represents a contiguous partition of the alloca. These are
> +/// formed by examining the uses of the alloca. During formation, they may
> +/// overlap but once an AllocaPartitioning is built, the Partitions within it
> +/// are all disjoint.
> +struct Partition : public ByteRange {
> +  /// \brief Whether this partition is splittable into smaller partitions.
> +  ///
> +  /// We flag partitions as splittable when they are formed entirely due to
> +  /// accesses by trivially splittable operations such as memset and memcpy.
> +  bool IsSplittable;
> +
> +  /// \brief Test whether a partition has been marked as dead.
> +  bool isDead() const {
> +    if (BeginOffset == UINT64_MAX) {
> +      assert(EndOffset == UINT64_MAX);
> +      return true;
> +    }
> +    return false;
> +  }
> +
> +  /// \brief Kill a partition.
> +  /// This is accomplished by setting both its beginning and end offset to
> +  /// the maximum possible value.
> +  void kill() {
> +    assert(!isDead() && "He's Dead, Jim!");
> +    BeginOffset = EndOffset = UINT64_MAX;
> +  }
> +
> +  Partition() : ByteRange(), IsSplittable() {}
> +  Partition(uint64_t BeginOffset, uint64_t EndOffset, bool IsSplittable)
> +      : ByteRange(BeginOffset, EndOffset), IsSplittable(IsSplittable) {}
> +};
> 
> -    /// \brief Set the use for this partition use range.
> -    void setUse(Use *U) { UsePtrAndIsSplit.setPointer(U); }
> +/// \brief A particular use of a partition of the alloca.
> +///
> +/// This structure is used to associate uses of a partition with it. They
> +/// mark the range of bytes which are referenced by a particular instruction,
> +/// and includes a handle to the user itself and the pointer value in use.
> +/// The bounds of these uses are determined by intersecting the bounds of the
> +/// memory use itself with a particular partition. As a consequence there is
> +/// intentionally overlap between various uses of the same partition.
> +class PartitionUse : public ByteRange {
> +  /// \brief Combined storage for both the Use* and split state.
> +  PointerIntPair<Use*, 1, bool> UsePtrAndIsSplit;
> 
> -    /// \brief Whether this use is split across multiple partitions.
> -    bool isSplit() const { return UsePtrAndIsSplit.getInt(); }
> -  };
> +public:
> +  PartitionUse() : ByteRange(), UsePtrAndIsSplit() {}
> +  PartitionUse(uint64_t BeginOffset, uint64_t EndOffset, Use *U,
> +               bool IsSplit)
> +      : ByteRange(BeginOffset, EndOffset), UsePtrAndIsSplit(U, IsSplit) {}
> +
> +  /// \brief The use in question. Provides access to both user and used value.
> +  ///
> +  /// Note that this may be null if the partition use is *dead*, that is, it
> +  /// should be ignored.
> +  Use *getUse() const { return UsePtrAndIsSplit.getPointer(); }
> +
> +  /// \brief Set the use for this partition use range.
> +  void setUse(Use *U) { UsePtrAndIsSplit.setPointer(U); }
> +
> +  /// \brief Whether this use is split across multiple partitions.
> +  bool isSplit() const { return UsePtrAndIsSplit.getInt(); }
> +};
> +}
> 
> +namespace llvm {
> +template <> struct isPodLike<Partition> : llvm::true_type {};
> +template <> struct isPodLike<PartitionUse> : llvm::true_type {};
> +}
> +
> +namespace {
> +/// \brief Alloca partitioning representation.
> +///
> +/// This class represents a partitioning of an alloca into slices, and
> +/// information about the nature of uses of each slice of the alloca. The goal
> +/// is that this information is sufficient to decide if and how to split the
> +/// alloca apart and replace slices with scalars. It is also intended that this
> +/// structure can capture the relevant information needed both to decide about
> +/// and to enact these transformations.
> +class AllocaPartitioning {
> +public:
>   /// \brief Construct a partitioning of a particular alloca.
>   ///
>   /// Construction does most of the work for partitioning the alloca. This
> @@ -1389,7 +1396,7 @@ public:
>     // may be grown during speculation. However, we never need to re-visit the
>     // new uses, and so we can use the initial size bound.
>     for (unsigned Idx = 0, Size = P.use_size(PI); Idx != Size; ++Idx) {
> -      const AllocaPartitioning::PartitionUse &PU = P.getUse(PI, Idx);
> +      const PartitionUse &PU = P.getUse(PI, Idx);
>       if (!PU.getUse())
>         continue; // Skip dead use.
> 
> @@ -1594,7 +1601,7 @@ private:
>     IRBuilder<> IRB(&SI);
>     Use *Ops[2] = { &SI.getOperandUse(1), &SI.getOperandUse(2) };
>     AllocaPartitioning::iterator PIs[2];
> -    AllocaPartitioning::PartitionUse PUs[2];
> +    PartitionUse PUs[2];
>     for (unsigned i = 0, e = 2; i != e; ++i) {
>       PIs[i] = P.findPartitionForPHIOrSelectOperand(Ops[i]);
>       if (PIs[i] != P.end()) {
> 
> 
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20130319/4aa1d2db/attachment.html>


More information about the llvm-commits mailing list