#include <cassert>
#include <cstddef>
#include <iterator>
+#include <type_traits>
namespace llvm {
typedef typename super::pointer pointer;
typedef typename super::reference reference;
+ typedef typename std::add_const<value_type>::type *const_pointer;
+ typedef typename std::add_const<value_type>::type &const_reference;
+
typedef typename ilist_detail::ConstCorrectNodeType<NodeTy>::type node_type;
typedef node_type *node_pointer;
typedef node_type &node_reference;
// This is templated so that we can allow constructing a const iterator from
// a nonconst iterator...
template <class node_ty>
- ilist_iterator(const ilist_iterator<node_ty> &RHS)
+ ilist_iterator(
+ const ilist_iterator<node_ty> &RHS,
+ typename std::enable_if<std::is_convertible<node_ty *, NodeTy *>::value,
+ void *>::type = nullptr)
: NodePtr(RHS.getNodePtrUnchecked()) {}
// This is templated so that we can allow assigning to a const iterator from
void reset(pointer NP) { NodePtr = NP; }
// Accessors...
- explicit operator pointer() const { return NodePtr; }
reference operator*() const { return *NodePtr; }
pointer operator->() const { return &operator*(); }
// Comparison operators
- template <class Y> bool operator==(const ilist_iterator<Y> &RHS) const {
- return NodePtr == RHS.getNodePtrUnchecked();
+ friend bool operator==(const ilist_iterator &LHS, const ilist_iterator &RHS) {
+ return LHS.NodePtr == RHS.NodePtr;
}
- template <class Y> bool operator!=(const ilist_iterator<Y> &RHS) const {
- return NodePtr != RHS.getNodePtrUnchecked();
+ friend bool operator!=(const ilist_iterator &LHS, const ilist_iterator &RHS) {
+ return LHS.NodePtr != RHS.NodePtr;
}
// Increment and decrement operators...
template <typename Ty>
class MachineInstrBundleIterator
: public std::iterator<std::bidirectional_iterator_tag, Ty, ptrdiff_t> {
+ typedef std::iterator<std::bidirectional_iterator_tag, Ty, ptrdiff_t> super;
typedef ilist_iterator<Ty> instr_iterator;
instr_iterator MII;
public:
+ typedef typename super::value_type value_type;
+ typedef typename super::difference_type difference_type;
+ typedef typename super::pointer pointer;
+ typedef typename super::reference reference;
+
+ typedef typename instr_iterator::const_pointer const_pointer;
+ typedef typename instr_iterator::const_reference const_reference;
+
MachineInstrBundleIterator(instr_iterator MI) : MII(MI) {}
- MachineInstrBundleIterator(Ty &MI) : MII(MI) {
+ MachineInstrBundleIterator(reference MI) : MII(MI) {
assert(!MI.isBundledWithPred() && "It's not legal to initialize "
"MachineInstrBundleIterator with a "
"bundled MI");
}
- MachineInstrBundleIterator(Ty *MI) : MII(MI) {
+ MachineInstrBundleIterator(pointer MI) : MII(MI) {
// FIXME: This conversion should be explicit.
assert((!MI || !MI->isBundledWithPred()) && "It's not legal to initialize "
"MachineInstrBundleIterator "
}
// Template allows conversion from const to nonconst.
template <class OtherTy>
- MachineInstrBundleIterator(const MachineInstrBundleIterator<OtherTy> &I)
+ MachineInstrBundleIterator(
+ const MachineInstrBundleIterator<OtherTy> &I,
+ typename std::enable_if<std::is_convertible<OtherTy *, Ty *>::value,
+ void *>::type = nullptr)
: MII(I.getInstrIterator()) {}
MachineInstrBundleIterator() : MII(nullptr) {}
- Ty &operator*() const { return *MII; }
- Ty *operator->() const { return &operator*(); }
+ reference operator*() const { return *MII; }
+ pointer operator->() const { return &operator*(); }
- // FIXME: This should be implemented as "return &operator*()" (or removed).
- explicit operator Ty *() const { return MII.getNodePtrUnchecked(); }
+ /// Check for null.
+ bool isValid() const { return MII.getNodePtr(); }
- bool operator==(const MachineInstrBundleIterator &X) const {
- return MII == X.MII;
+ friend bool operator==(const MachineInstrBundleIterator &L,
+ const MachineInstrBundleIterator &R) {
+ return L.MII == R.MII;
+ }
+ friend bool operator==(const MachineInstrBundleIterator &L, const_pointer R) {
+ // Avoid assertion about validity of R.
+ return L.MII == instr_iterator(const_cast<pointer>(R));
+ }
+ friend bool operator==(const_pointer L, const MachineInstrBundleIterator &R) {
+ // Avoid assertion about validity of L.
+ return instr_iterator(const_cast<pointer>(L)) == R.MII;
+ }
+ friend bool operator==(const MachineInstrBundleIterator &L,
+ const_reference R) {
+ return L == &R; // Avoid assertion about validity of R.
+ }
+ friend bool operator==(const_reference L,
+ const MachineInstrBundleIterator &R) {
+ return &L == R; // Avoid assertion about validity of L.
+ }
+
+ friend bool operator!=(const MachineInstrBundleIterator &L,
+ const MachineInstrBundleIterator &R) {
+ return !(L == R);
+ }
+ friend bool operator!=(const MachineInstrBundleIterator &L, const_pointer R) {
+ return !(L == R);
+ }
+ friend bool operator!=(const_pointer L, const MachineInstrBundleIterator &R) {
+ return !(L == R);
+ }
+ friend bool operator!=(const MachineInstrBundleIterator &L,
+ const_reference R) {
+ return !(L == R);
}
- bool operator!=(const MachineInstrBundleIterator &X) const {
- return !operator==(X);
+ friend bool operator!=(const_reference L,
+ const MachineInstrBundleIterator &R) {
+ return !(L == R);
}
// Increment and decrement operators...
void FastISel::removeDeadCode(MachineBasicBlock::iterator I,
MachineBasicBlock::iterator E) {
- assert(static_cast<MachineInstr *>(I) && static_cast<MachineInstr *>(E) &&
- std::distance(I, E) > 0 && "Invalid iterator!");
+ assert(I.isValid() && E.isValid() && std::distance(I, E) > 0 &&
+ "Invalid iterator!");
while (I != E) {
MachineInstr *Dead = &*I;
++I;
void AMDGPUCFGStructurizer::reversePredicateSetter(
MachineBasicBlock::iterator I) {
- assert(static_cast<MachineInstr *>(I) && "Expected valid iterator");
+ assert(I.isValid() && "Expected valid iterator");
for (;; --I) {
if (I->getOpcode() == AMDGPU::PRED_X) {
- switch (static_cast<MachineInstr *>(I)->getOperand(2).getImm()) {
+ switch (I->getOperand(2).getImm()) {
case OPCODE_IS_ZERO_INT:
- static_cast<MachineInstr *>(I)->getOperand(2)
- .setImm(OPCODE_IS_NOT_ZERO_INT);
+ I->getOperand(2).setImm(OPCODE_IS_NOT_ZERO_INT);
return;
case OPCODE_IS_NOT_ZERO_INT:
- static_cast<MachineInstr *>(I)->getOperand(2)
- .setImm(OPCODE_IS_ZERO_INT);
+ I->getOperand(2).setImm(OPCODE_IS_ZERO_INT);
return;
case OPCODE_IS_ZERO:
- static_cast<MachineInstr *>(I)->getOperand(2)
- .setImm(OPCODE_IS_NOT_ZERO);
+ I->getOperand(2).setImm(OPCODE_IS_NOT_ZERO);
return;
case OPCODE_IS_NOT_ZERO:
- static_cast<MachineInstr *>(I)->getOperand(2)
- .setImm(OPCODE_IS_ZERO);
+ I->getOperand(2).setImm(OPCODE_IS_ZERO);
return;
default:
llvm_unreachable("PRED_X Opcode invalid!");
// handled
if (isBranch(I->getOpcode()))
return true;
- if (!isJump(static_cast<MachineInstr *>(I)->getOpcode())) {
+ if (!isJump(I->getOpcode())) {
return false;
}
// If there is only one terminator instruction, process it.
unsigned LastOpc = LastInst.getOpcode();
- if (I == MBB.begin() ||
- !isJump(static_cast<MachineInstr *>(--I)->getOpcode())) {
+ if (I == MBB.begin() || !isJump((--I)->getOpcode())) {
if (LastOpc == AMDGPU::JUMP) {
TBB = LastInst.getOperand(0).getMBB();
return false;
for (auto NewMI : DbgMItoMove) {
// If iterator MI is pointing to DEBUG_VAL, make sure
// MI now points to next relevant instruction.
- if (NewMI == (MachineInstr*)MI)
+ if (NewMI == MI)
++MI;
BB->splice(InsertPt, BB, NewMI);
}
Offset < BaseInsertOffset;
Offset += TII->getInstSizeInBytes(*MI), MI = std::next(MI)) {
assert(MI != UserMBB->end() && "Fell off end of block");
- if (CPUIndex < NumCPUsers &&
- CPUsers[CPUIndex].MI == static_cast<MachineInstr *>(MI)) {
+ if (CPUIndex < NumCPUsers && CPUsers[CPUIndex].MI == MI) {
CPUser &U = CPUsers[CPUIndex];
if (!isOffsetInRange(Offset, EndInsertOffset, U)) {
// Shift intertion point by one unit of alignment so it is within reach.
set(CodeGenSources
DIEHashTest.cpp
LowLevelTypeTest.cpp
+ MachineInstrBundleIteratorTest.cpp
)
add_llvm_unittest(CodeGenTests
--- /dev/null
+//===- MachineInstrBundleIteratorTest.cpp ---------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/ilist_node.h"
+#include "llvm/CodeGen/MachineInstrBundleIterator.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+struct MyBundledInstr : public ilist_node<MyBundledInstr> {
+ bool isBundledWithPred() const { return true; }
+ bool isBundledWithSucc() const { return true; }
+};
+typedef MachineInstrBundleIterator<MyBundledInstr> bundled_iterator;
+typedef MachineInstrBundleIterator<const MyBundledInstr> const_bundled_iterator;
+
+#ifdef GTEST_HAS_DEATH_TEST
+#ifndef NDEBUG
+TEST(MachineInstrBundleIteratorTest, CheckForBundles) {
+ MyBundledInstr MBI;
+
+ // Confirm that MBI is always considered bundled.
+ EXPECT_TRUE(MBI.isBundledWithPred());
+ EXPECT_TRUE(MBI.isBundledWithSucc());
+
+ // Confirm that iterators check in their constructor for bundled iterators.
+ EXPECT_DEATH((void)static_cast<bundled_iterator>(MBI),
+ "not legal to initialize");
+ EXPECT_DEATH((void)static_cast<bundled_iterator>(&MBI),
+ "not legal to initialize");
+ EXPECT_DEATH((void)static_cast<const_bundled_iterator>(MBI),
+ "not legal to initialize");
+ EXPECT_DEATH((void)static_cast<const_bundled_iterator>(&MBI),
+ "not legal to initialize");
+}
+#endif
+#endif
+
+TEST(MachineInstrBundleIteratorTest, CompareToBundledMI) {
+ MyBundledInstr MBI;
+ const MyBundledInstr &CMBI = MBI;
+ bundled_iterator I;
+ const_bundled_iterator CI;
+
+ // Confirm that MBI is always considered bundled.
+ EXPECT_TRUE(MBI.isBundledWithPred());
+ EXPECT_TRUE(MBI.isBundledWithSucc());
+
+ // These invocations will crash when !NDEBUG if a conversion is taking place.
+ // These checks confirm that comparison operators don't use any conversion
+ // operators.
+ ASSERT_FALSE(MBI == I);
+ ASSERT_FALSE(&MBI == I);
+ ASSERT_FALSE(CMBI == I);
+ ASSERT_FALSE(&CMBI == I);
+ ASSERT_FALSE(I == MBI);
+ ASSERT_FALSE(I == &MBI);
+ ASSERT_FALSE(I == CMBI);
+ ASSERT_FALSE(I == &CMBI);
+ ASSERT_FALSE(MBI == CI);
+ ASSERT_FALSE(&MBI == CI);
+ ASSERT_FALSE(CMBI == CI);
+ ASSERT_FALSE(&CMBI == CI);
+ ASSERT_FALSE(CI == MBI);
+ ASSERT_FALSE(CI == &MBI);
+ ASSERT_FALSE(CI == CMBI);
+ ASSERT_FALSE(CI == &CMBI);
+ ASSERT_TRUE(MBI != I);
+ ASSERT_TRUE(&MBI != I);
+ ASSERT_TRUE(CMBI != I);
+ ASSERT_TRUE(&CMBI != I);
+ ASSERT_TRUE(I != MBI);
+ ASSERT_TRUE(I != &MBI);
+ ASSERT_TRUE(I != CMBI);
+ ASSERT_TRUE(I != &CMBI);
+ ASSERT_TRUE(MBI != CI);
+ ASSERT_TRUE(&MBI != CI);
+ ASSERT_TRUE(CMBI != CI);
+ ASSERT_TRUE(&CMBI != CI);
+ ASSERT_TRUE(CI != MBI);
+ ASSERT_TRUE(CI != &MBI);
+ ASSERT_TRUE(CI != CMBI);
+ ASSERT_TRUE(CI != &CMBI);
+}
+
+} // end namespace