Skip to content

Commit

Permalink
First chunk of MachineInstr bundle support.
Browse files Browse the repository at this point in the history
1. Added opcode BUNDLE
2. Taught MachineInstr class to deal with bundled MIs
3. Changed MachineBasicBlock iterator to skip over bundled MIs; added an iterator to walk all the MIs
4. Taught MachineBasicBlock methods about bundled MIs


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@145975 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
Evan Cheng committed Dec 6, 2011
1 parent 3d5d8f6 commit 7c2a4a3
Show file tree
Hide file tree
Showing 19 changed files with 369 additions and 69 deletions.
202 changes: 179 additions & 23 deletions include/llvm/CodeGen/MachineBasicBlock.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,10 +129,89 @@ class MachineBasicBlock : public ilist_node<MachineBasicBlock> {
const MachineFunction *getParent() const { return xParent; }
MachineFunction *getParent() { return xParent; }

typedef Instructions::iterator iterator;
typedef Instructions::const_iterator const_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;

/// bundle_iterator - MachineBasicBlock iterator that automatically skips over
/// MIs that are inside bundles (i.e. walk top level MIs only).
template<typename Ty, typename IterTy>
class bundle_iterator
: public std::iterator<std::bidirectional_iterator_tag, Ty, ptrdiff_t> {
IterTy MII;

public:
bundle_iterator(IterTy mii) : MII(mii) {
assert(!MII->isInsideBundle() &&
"It's not legal to initialize bundle_iterator with a bundled MI");
}

bundle_iterator(Ty &mi) : MII(mi) {
assert(!mi.isInsideBundle() &&
"It's not legal to initialize bundle_iterator with a bundled MI");
}
bundle_iterator(Ty *mi) : MII(mi) {
assert((!mi || !mi->isInsideBundle()) &&
"It's not legal to initialize bundle_iterator with a bundled MI");
}
bundle_iterator(const bundle_iterator &I) : MII(I.MII) {}
bundle_iterator() : MII(0) {}

Ty &operator*() const { return *MII; }
Ty *operator->() const { return &operator*(); }

operator Ty*() const { return MII; }

bool operator==(const bundle_iterator &x) const {
return MII == x.MII;
}
bool operator!=(const bundle_iterator &x) const {
return !operator==(x);
}

// Increment and decrement operators...
bundle_iterator &operator--() { // predecrement - Back up
do {
--MII;
} while (MII->isInsideBundle());
return *this;
}
bundle_iterator &operator++() { // preincrement - Advance
do {
++MII;
} while (MII->isInsideBundle());
return *this;
}
bundle_iterator operator--(int) { // postdecrement operators...
bundle_iterator tmp = *this;
do {
--MII;
} while (MII->isInsideBundle());
return tmp;
}
bundle_iterator operator++(int) { // postincrement operators...
bundle_iterator tmp = *this;
do {
++MII;
} while (MII->isInsideBundle());
return tmp;
}

IterTy getInsnIterator() const {
return MII;
}
};

typedef Instructions::iterator insn_iterator;
typedef Instructions::const_iterator const_insn_iterator;
typedef std::reverse_iterator<insn_iterator> reverse_insn_iterator;
typedef
std::reverse_iterator<const_insn_iterator> const_reverse_insn_iterator;

typedef
bundle_iterator<MachineInstr,insn_iterator> iterator;
typedef
bundle_iterator<const MachineInstr,const_insn_iterator> const_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;


unsigned size() const { return (unsigned)Insts.size(); }
bool empty() const { return Insts.empty(); }
Expand All @@ -142,15 +221,53 @@ class MachineBasicBlock : public ilist_node<MachineBasicBlock> {
const MachineInstr& front() const { return Insts.front(); }
const MachineInstr& back() const { return Insts.back(); }

insn_iterator insn_begin() { return Insts.begin(); }
const_insn_iterator insn_begin() const { return Insts.begin(); }
insn_iterator insn_end() { return Insts.end(); }
const_insn_iterator insn_end() const { return Insts.end(); }
reverse_insn_iterator insn_rbegin() { return Insts.rbegin(); }
const_reverse_insn_iterator insn_rbegin() const { return Insts.rbegin(); }
reverse_insn_iterator insn_rend () { return Insts.rend(); }
const_reverse_insn_iterator insn_rend () const { return Insts.rend(); }

iterator begin() { return Insts.begin(); }
const_iterator begin() const { return Insts.begin(); }
iterator end() { return Insts.end(); }
const_iterator end() const { return Insts.end(); }
reverse_iterator rbegin() { return Insts.rbegin(); }
const_reverse_iterator rbegin() const { return Insts.rbegin(); }
iterator end() {
insn_iterator II = insn_end();
if (II != insn_begin()) {
while (II->isInsideBundle())
--II;
}
return II;
}
const_iterator end() const {
const_insn_iterator II = insn_end();
if (II != insn_begin()) {
while (II->isInsideBundle())
--II;
}
return II;
}
reverse_iterator rbegin() {
reverse_insn_iterator II = insn_rbegin();
if (II != insn_rend()) {
while (II->isInsideBundle())
++II;
}
return II;
}
const_reverse_iterator rbegin() const {
const_reverse_insn_iterator II = insn_rbegin();
if (II != insn_rend()) {
while (II->isInsideBundle())
++II;
}
return II;
}
reverse_iterator rend () { return Insts.rend(); }
const_reverse_iterator rend () const { return Insts.rend(); }


// Machine-CFG iterators
typedef std::vector<MachineBasicBlock *>::iterator pred_iterator;
typedef std::vector<MachineBasicBlock *>::const_iterator const_pred_iterator;
Expand Down Expand Up @@ -323,18 +440,16 @@ class MachineBasicBlock : public ilist_node<MachineBasicBlock> {
/// instruction of this basic block. If a terminator does not exist,
/// it returns end()
iterator getFirstTerminator();
const_iterator getFirstTerminator() const;

const_iterator getFirstTerminator() const {
return const_cast<MachineBasicBlock*>(this)->getFirstTerminator();
}
/// getFirstInsnTerminator - Same getFirstTerminator but it ignores bundles
/// and return an insn_iterator instead.
insn_iterator getFirstInsnTerminator();

/// getLastNonDebugInstr - returns an iterator to the last non-debug
/// instruction in the basic block, or end()
iterator getLastNonDebugInstr();

const_iterator getLastNonDebugInstr() const {
return const_cast<MachineBasicBlock*>(this)->getLastNonDebugInstr();
}
const_iterator getLastNonDebugInstr() const;

/// SplitCriticalEdge - Split the critical edge from this block to the
/// given successor block, and return the newly created block, or null
Expand All @@ -347,32 +462,70 @@ class MachineBasicBlock : public ilist_node<MachineBasicBlock> {
void pop_front() { Insts.pop_front(); }
void pop_back() { Insts.pop_back(); }
void push_back(MachineInstr *MI) { Insts.push_back(MI); }

template<typename IT>
void insert(iterator I, IT S, IT E) { Insts.insert(I, S, E); }
iterator insert(iterator I, MachineInstr *M) { return Insts.insert(I, M); }
iterator insertAfter(iterator I, MachineInstr *M) {
void insert(insn_iterator I, IT S, IT E) {
Insts.insert(I, S, E);
}
insn_iterator insert(insn_iterator I, MachineInstr *M) {
return Insts.insert(I, M);
}
insn_iterator insertAfter(insn_iterator I, MachineInstr *M) {
return Insts.insertAfter(I, M);
}

template<typename IT>
void insert(iterator I, IT S, IT E) {
Insts.insert(I.getInsnIterator(), S, E);
}
iterator insert(iterator I, MachineInstr *M) {
return Insts.insert(I.getInsnIterator(), M);
}
iterator insertAfter(iterator I, MachineInstr *M) {
return Insts.insertAfter(I.getInsnIterator(), M);
}

// erase - Remove the specified element or range from the instruction list.
// These functions delete any instructions removed.
//
iterator erase(iterator I) { return Insts.erase(I); }
iterator erase(iterator I, iterator E) { return Insts.erase(I, E); }
insn_iterator erase(insn_iterator I) {
return Insts.erase(I);
}
insn_iterator erase(insn_iterator I, insn_iterator E) {
return Insts.erase(I, E);
}

iterator erase(iterator I) {
return Insts.erase(I.getInsnIterator());
}
iterator erase(iterator I, iterator E) {
return Insts.erase(I.getInsnIterator(), E.getInsnIterator());
}

iterator erase(MachineInstr *I) { iterator MII(I); return erase(MII); }
MachineInstr *remove(MachineInstr *I) { return Insts.remove(I); }
void clear() { Insts.clear(); }

/// splice - Take an instruction from MBB 'Other' at the position From,
/// and insert it into this MBB right before 'where'.
void splice(iterator where, MachineBasicBlock *Other, iterator From) {
void splice(insn_iterator where, MachineBasicBlock *Other,
insn_iterator From) {
Insts.splice(where, Other->Insts, From);
}
void splice(iterator where, MachineBasicBlock *Other, iterator From) {
Insts.splice(where.getInsnIterator(), Other->Insts, From.getInsnIterator());
}

/// splice - Take a block of instructions from MBB 'Other' in the range [From,
/// To), and insert them into this MBB right before 'where'.
void splice(insn_iterator where, MachineBasicBlock *Other, insn_iterator From,
insn_iterator To) {
Insts.splice(where, Other->Insts, From, To);
}
void splice(iterator where, MachineBasicBlock *Other, iterator From,
iterator To) {
Insts.splice(where, Other->Insts, From, To);
Insts.splice(where.getInsnIterator(), Other->Insts,
From.getInsnIterator(), To.getInsnIterator());
}

/// removeFromParent - This method unlinks 'this' from the containing
Expand All @@ -399,7 +552,10 @@ class MachineBasicBlock : public ilist_node<MachineBasicBlock> {

/// findDebugLoc - find the next valid DebugLoc starting at MBBI, skipping
/// any DBG_VALUE instructions. Return UnknownLoc if there is none.
DebugLoc findDebugLoc(MachineBasicBlock::iterator &MBBI);
DebugLoc findDebugLoc(insn_iterator MBBI);
DebugLoc findDebugLoc(iterator MBBI) {
return findDebugLoc(MBBI.getInsnIterator());
}

// Debugging methods.
void dump() const;
Expand Down
60 changes: 55 additions & 5 deletions include/llvm/CodeGen/MachineInstr.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,11 @@ class MachineInstr : public ilist_node<MachineInstr> {
};

enum MIFlag {
NoFlags = 0,
FrameSetup = 1 << 0 // Instruction is used as a part of
NoFlags = 0,
FrameSetup = 1 << 0, // Instruction is used as a part of
// function frame setup code.
InsideBundle = 1 << 1 // Instruction is inside a bundle (not
// the first MI in a bundle)
};
private:
const MCInstrDesc *MCID; // Instruction descriptor.
Expand Down Expand Up @@ -148,6 +150,12 @@ class MachineInstr : public ilist_node<MachineInstr> {
AsmPrinterFlags |= (uint8_t)Flag;
}

/// clearAsmPrinterFlag - clear specific AsmPrinter flags
///
void clearAsmPrinterFlag(CommentFlag Flag) {
AsmPrinterFlags &= ~Flag;
}

/// getFlags - Return the MI flags bitvector.
uint8_t getFlags() const {
return Flags;
Expand All @@ -167,10 +175,44 @@ class MachineInstr : public ilist_node<MachineInstr> {
Flags = flags;
}

/// clearAsmPrinterFlag - clear specific AsmPrinter flags
/// isInsideBundle - Return true if MI is in a bundle (but not the first MI
/// in a bundle).
///
void clearAsmPrinterFlag(CommentFlag Flag) {
AsmPrinterFlags &= ~Flag;
/// A bundle looks like this before it's finalized:
/// ----------------
/// | MI |
/// ----------------
/// |
/// ----------------
/// | MI * |
/// ----------------
/// |
/// ----------------
/// | MI * |
/// ----------------
/// In this case, the first MI starts a bundle but is not inside a bundle, the
/// next 2 MIs are considered "inside" the bundle.
///
/// After a bundle is finalized, it looks like this:
/// ----------------
/// | Bundle |
/// ----------------
/// |
/// ----------------
/// | MI * |
/// ----------------
/// |
/// ----------------
/// | MI * |
/// ----------------
/// |
/// ----------------
/// | MI * |
/// ----------------
/// The first instruction has the special opcode "BUNDLE". It's not "inside"
/// a bundle, but the next three MIs are.
bool isInsideBundle() const {
return getFlag(InsideBundle);
}

/// getDebugLoc - Returns the debug location id of this MachineInstr.
Expand Down Expand Up @@ -232,6 +274,14 @@ class MachineInstr : public ilist_node<MachineInstr> {
return MemRefsEnd - MemRefs == 1;
}

/// API for querying MachineInstr properties. These are bundle aware.
///
bool hasProperty(unsigned short Flag) const;

bool isTerminator() const {
return hasProperty(MCID::Terminator);
}

enum MICheckType {
CheckDefs, // Check all operands for equality
CheckKillDead, // Check all operands including kill / dead markers
Expand Down
4 changes: 4 additions & 0 deletions include/llvm/MC/MCInstrDesc.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,10 @@ class MCInstrDesc {
return NumDefs;
}

/// getFlags - Return flags of this instruction.
///
unsigned short getFlags() const { return Flags; }

/// isVariadic - Return true if this instruction can have a variable number of
/// operands. In this case, the variable operands will be after the normal
/// operands but before the implicit definitions and uses (if any are
Expand Down
5 changes: 5 additions & 0 deletions include/llvm/Target/Target.td
Original file line number Diff line number Diff line change
Expand Up @@ -688,6 +688,11 @@ def COPY : Instruction {
let neverHasSideEffects = 1;
let isAsCheapAsAMove = 1;
}
def BUNDLE : Instruction {
let OutOperandList = (outs);
let InOperandList = (ins variable_ops);
let AsmString = "BUNDLE";
}
}

//===----------------------------------------------------------------------===//
Expand Down
7 changes: 6 additions & 1 deletion include/llvm/Target/TargetOpcodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,12 @@ namespace TargetOpcode {

/// COPY - Target-independent register copy. This instruction can also be
/// used to copy between subregisters of virtual registers.
COPY = 13
COPY = 13,

/// BUNDLE - This instruction represents an instruction bundle. Instructions
/// which immediately follow a BUNDLE instruction which are marked with
/// 'InsideBundle' flag are inside the bundle.
BUNDLE
};
} // end namespace TargetOpcode
} // end namespace llvm
Expand Down
Loading

0 comments on commit 7c2a4a3

Please sign in to comment.