#ifndef LLVM_ADT_SMALLPTRSET_H
#define LLVM_ADT_SMALLPTRSET_H
+#include "llvm/Config/abi-breaking.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/PointerLikeTypeTraits.h"
#include <cassert>
#include <iterator>
#include <utility>
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
+namespace llvm {
+template <class T = void> struct ReverseIterate { static bool value; };
+template <class T> bool ReverseIterate<T>::value = true;
+}
+#endif
+
namespace llvm {
/// SmallPtrSetImplBase - This is the common code shared among all the
public:
explicit SmallPtrSetIteratorImpl(const void *const *BP, const void*const *E)
: Bucket(BP), End(E) {
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
+ if (ReverseIterate<bool>::value) {
+ RetreatIfNotValid();
+ return;
+ }
+#endif
AdvanceIfNotValid();
}
*Bucket == SmallPtrSetImplBase::getTombstoneMarker()))
++Bucket;
}
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
+ void RetreatIfNotValid() {
+ --Bucket;
+ assert(Bucket <= End);
+ while (Bucket != End &&
+ (*Bucket == SmallPtrSetImplBase::getEmptyMarker() ||
+ *Bucket == SmallPtrSetImplBase::getTombstoneMarker())) {
+ --Bucket;
+ }
+ }
+#endif
};
/// SmallPtrSetIterator - This implements a const_iterator for SmallPtrSet.
}
inline SmallPtrSetIterator& operator++() { // Preincrement
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
+ if (ReverseIterate<bool>::value) {
+ RetreatIfNotValid();
+ return *this;
+ }
+#endif
++Bucket;
AdvanceIfNotValid();
return *this;
}
SmallPtrSetIterator operator++(int) { // Postincrement
- SmallPtrSetIterator tmp = *this; ++*this; return tmp;
+ SmallPtrSetIterator tmp = *this;
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
+ if (ReverseIterate<bool>::value) {
+ --*this;
+ return tmp;
+ }
+#endif
+ ++*this;
+ return tmp;
}
};
}
inline iterator begin() const {
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
+ if (ReverseIterate<bool>::value)
+ return endPtr();
+#endif
return iterator(CurArray, EndPointer());
}
inline iterator end() const {
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
+ if (ReverseIterate<bool>::value)
+ return iterator(CurArray, CurArray);
+#endif
+ return endPtr();
+ }
+
+private:
+ inline iterator endPtr() const {
const void *const *End = EndPointer();
return iterator(End, End);
}
#define DEBUG_TYPE "commandline"
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
+namespace llvm {
+// If LLVM_ENABLE_ABI_BREAKING_CHECKS is set the flag -mllvm -reverse-iterate
+// can be used to toggle forward/reverse iteration of unordered containers.
+// This will help uncover differences in codegen caused due to undefined
+// iteration order.
+static cl::opt<bool, true> ReverseIteration("reverse-iterate",
+ cl::location(ReverseIterate<bool>::value), cl::init(true));
+}
+#endif
+
//===----------------------------------------------------------------------===//
// Template instantiations and anchors.
//
--- /dev/null
+//===- llvm/unittest/ADT/ReverseIterationTest.cpp ------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// ReverseIteration unit tests.
+//
+//===----------------------------------------------------------------------===//
+
+#include "gtest/gtest.h"
+#include "llvm/ADT/SmallPtrSet.h"
+
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
+using namespace llvm;
+
+TEST(ReverseIterationTest, SmallPtrSetTest) {
+
+ SmallPtrSet<void*, 4> Set;
+ void *Ptrs[] = { (void*)0x1, (void*)0x2, (void*)0x3, (void*)0x4 };
+ void *ReversePtrs[] = { (void*)0x4, (void*)0x3, (void*)0x2, (void*)0x1 };
+
+ for (auto *Ptr: Ptrs)
+ Set.insert(Ptr);
+
+ // Check forward iteration.
+ ReverseIterate<bool>::value = false;
+ for (const auto &Tuple : zip(Set, Ptrs))
+ ASSERT_EQ(std::get<0>(Tuple), std::get<1>(Tuple));
+
+ // Check reverse iteration.
+ ReverseIterate<bool>::value = true;
+ for (const auto &Tuple : zip(Set, ReversePtrs))
+ ASSERT_EQ(std::get<0>(Tuple), std::get<1>(Tuple));
+}
+#endif