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