aboutsummaryrefslogtreecommitdiffstats
path: root/include/llvm/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/CodeGen')
-rw-r--r--include/llvm/CodeGen/Analysis.h4
-rw-r--r--include/llvm/CodeGen/AsmPrinter.h5
-rw-r--r--include/llvm/CodeGen/DFAPacketizer.h78
-rw-r--r--include/llvm/CodeGen/EdgeBundles.h3
-rw-r--r--include/llvm/CodeGen/FastISel.h11
-rw-r--r--include/llvm/CodeGen/GCStrategy.h13
-rw-r--r--include/llvm/CodeGen/ISDOpcodes.h10
-rw-r--r--include/llvm/CodeGen/LinkAllCodegenComponents.h3
-rw-r--r--include/llvm/CodeGen/LiveInterval.h2
-rw-r--r--include/llvm/CodeGen/LiveIntervalAnalysis.h119
-rw-r--r--include/llvm/CodeGen/MachineBasicBlock.h229
-rw-r--r--include/llvm/CodeGen/MachineBlockFrequencyInfo.h4
-rw-r--r--include/llvm/CodeGen/MachineBranchProbabilityInfo.h12
-rw-r--r--include/llvm/CodeGen/MachineFrameInfo.h2
-rw-r--r--include/llvm/CodeGen/MachineFunction.h6
-rw-r--r--include/llvm/CodeGen/MachineFunctionAnalysis.h5
-rw-r--r--include/llvm/CodeGen/MachineInstr.h338
-rw-r--r--include/llvm/CodeGen/MachineInstrBuilder.h46
-rw-r--r--include/llvm/CodeGen/MachineInstrBundle.h34
-rw-r--r--include/llvm/CodeGen/MachineMemOperand.h6
-rw-r--r--include/llvm/CodeGen/MachineOperand.h27
-rw-r--r--include/llvm/CodeGen/Passes.h18
-rw-r--r--include/llvm/CodeGen/SchedulerRegistry.h9
-rw-r--r--include/llvm/CodeGen/SelectionDAG.h17
-rw-r--r--include/llvm/CodeGen/SelectionDAGISel.h4
-rw-r--r--include/llvm/CodeGen/SelectionDAGNodes.h11
-rw-r--r--include/llvm/CodeGen/SlotIndexes.h104
-rw-r--r--include/llvm/CodeGen/ValueTypes.h2
28 files changed, 865 insertions, 257 deletions
diff --git a/include/llvm/CodeGen/Analysis.h b/include/llvm/CodeGen/Analysis.h
index d8e6407..fda801c 100644
--- a/include/llvm/CodeGen/Analysis.h
+++ b/include/llvm/CodeGen/Analysis.h
@@ -70,6 +70,10 @@ bool hasInlineAsmMemConstraint(InlineAsm::ConstraintInfoVector &CInfos,
///
ISD::CondCode getFCmpCondCode(FCmpInst::Predicate Pred);
+/// getFCmpCodeWithoutNaN - Given an ISD condition code comparing floats,
+/// return the equivalent code if we're allowed to assume that NaNs won't occur.
+ISD::CondCode getFCmpCodeWithoutNaN(ISD::CondCode CC);
+
/// getICmpCondCode - Return the ISD condition code corresponding to
/// the given LLVM IR integer condition code.
///
diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h
index 06c5c83..f0d3423 100644
--- a/include/llvm/CodeGen/AsmPrinter.h
+++ b/include/llvm/CodeGen/AsmPrinter.h
@@ -194,6 +194,11 @@ namespace llvm {
bool needsSEHMoves();
+ /// needsRelocationsForDwarfStringPool - Specifies whether the object format
+ /// expects to use relocations to refer to debug entries. Alternatively we
+ /// emit section offsets in bytes from the start of the string pool.
+ bool needsRelocationsForDwarfStringPool() const;
+
/// EmitConstantPool - Print to the current output stream assembly
/// representations of the constants in the constant pool MCP. This is
/// used to print out constants which have been "spilled to memory" by
diff --git a/include/llvm/CodeGen/DFAPacketizer.h b/include/llvm/CodeGen/DFAPacketizer.h
new file mode 100644
index 0000000..0a11e0c
--- /dev/null
+++ b/include/llvm/CodeGen/DFAPacketizer.h
@@ -0,0 +1,78 @@
+//=- llvm/CodeGen/DFAPacketizer.h - DFA Packetizer for VLIW ---*- C++ -*-=====//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// This class implements a deterministic finite automaton (DFA) based
+// packetizing mechanism for VLIW architectures. It provides APIs to
+// determine whether there exists a legal mapping of instructions to
+// functional unit assignments in a packet. The DFA is auto-generated from
+// the target's Schedule.td file.
+//
+// A DFA consists of 3 major elements: states, inputs, and transitions. For
+// the packetizing mechanism, the input is the set of instruction classes for
+// a target. The state models all possible combinations of functional unit
+// consumption for a given set of instructions in a packet. A transition
+// models the addition of an instruction to a packet. In the DFA constructed
+// by this class, if an instruction can be added to a packet, then a valid
+// transition exists from the corresponding state. Invalid transitions
+// indicate that the instruction cannot be added to the current packet.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_DFAPACKETIZER_H
+#define LLVM_CODEGEN_DFAPACKETIZER_H
+
+#include "llvm/ADT/DenseMap.h"
+
+namespace llvm {
+
+class MCInstrDesc;
+class MachineInstr;
+class InstrItineraryData;
+
+class DFAPacketizer {
+private:
+ typedef std::pair<unsigned, unsigned> UnsignPair;
+ const InstrItineraryData *InstrItins;
+ int CurrentState;
+ const int (*DFAStateInputTable)[2];
+ const unsigned *DFAStateEntryTable;
+
+ // CachedTable is a map from <FromState, Input> to ToState.
+ DenseMap<UnsignPair, unsigned> CachedTable;
+
+ // ReadTable - Read the DFA transition table and update CachedTable.
+ void ReadTable(unsigned int state);
+
+public:
+ DFAPacketizer(const InstrItineraryData *I, const int (*SIT)[2],
+ const unsigned *SET);
+
+ // Reset the current state to make all resources available.
+ void clearResources() {
+ CurrentState = 0;
+ }
+
+ // canReserveResources - Check if the resources occupied by a MCInstrDesc
+ // are available in the current state.
+ bool canReserveResources(const llvm::MCInstrDesc *MID);
+
+ // reserveResources - Reserve the resources occupied by a MCInstrDesc and
+ // change the current state to reflect that change.
+ void reserveResources(const llvm::MCInstrDesc *MID);
+
+ // canReserveResources - Check if the resources occupied by a machine
+ // instruction are available in the current state.
+ bool canReserveResources(llvm::MachineInstr *MI);
+
+ // reserveResources - Reserve the resources occupied by a machine
+ // instruction and change the current state to reflect that change.
+ void reserveResources(llvm::MachineInstr *MI);
+};
+}
+
+#endif
diff --git a/include/llvm/CodeGen/EdgeBundles.h b/include/llvm/CodeGen/EdgeBundles.h
index 8aab3c6..a1d29b1 100644
--- a/include/llvm/CodeGen/EdgeBundles.h
+++ b/include/llvm/CodeGen/EdgeBundles.h
@@ -18,6 +18,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/IntEqClasses.h"
+#include "llvm/ADT/Twine.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
namespace llvm {
@@ -61,7 +62,7 @@ private:
/// Specialize WriteGraph, the standard implementation won't work.
raw_ostream &WriteGraph(raw_ostream &O, const EdgeBundles &G,
bool ShortNames = false,
- const std::string &Title = "");
+ const Twine &Title = "");
} // end namespace llvm
diff --git a/include/llvm/CodeGen/FastISel.h b/include/llvm/CodeGen/FastISel.h
index 18202d9..e57c8b1 100644
--- a/include/llvm/CodeGen/FastISel.h
+++ b/include/llvm/CodeGen/FastISel.h
@@ -21,9 +21,11 @@
namespace llvm {
class AllocaInst;
+class Constant;
class ConstantFP;
class FunctionLoweringInfo;
class Instruction;
+class LoadInst;
class MachineBasicBlock;
class MachineConstantPool;
class MachineFunction;
@@ -36,7 +38,8 @@ class TargetLowering;
class TargetMachine;
class TargetRegisterClass;
class TargetRegisterInfo;
-class LoadInst;
+class User;
+class Value;
/// FastISel - This is a fast-path instruction selection class that
/// generates poor code and doesn't support illegal types or non-trivial
@@ -358,6 +361,8 @@ private:
bool SelectExtractValue(const User *I);
+ bool SelectInsertValue(const User *I);
+
/// HandlePHINodesInSuccessorBlocks - Handle PHI nodes in successor blocks.
/// Emit code to ensure constants are copied into registers when needed.
/// Remember the virtual registers that need to be added to the Machine PHI
@@ -378,6 +383,10 @@ private:
/// hasTrivialKill - Test whether the given value has exactly one use.
bool hasTrivialKill(const Value *V) const;
+
+ /// removeDeadCode - Remove all dead instructions between the I and E.
+ void removeDeadCode(MachineBasicBlock::iterator I,
+ MachineBasicBlock::iterator E);
};
}
diff --git a/include/llvm/CodeGen/GCStrategy.h b/include/llvm/CodeGen/GCStrategy.h
index cd760db..1cbd36a 100644
--- a/include/llvm/CodeGen/GCStrategy.h
+++ b/include/llvm/CodeGen/GCStrategy.h
@@ -37,6 +37,7 @@
#define LLVM_CODEGEN_GCSTRATEGY_H
#include "llvm/CodeGen/GCMetadata.h"
+#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/Support/Registry.h"
#include <string>
@@ -68,6 +69,8 @@ namespace llvm {
bool CustomReadBarriers; //< Default is to insert loads.
bool CustomWriteBarriers; //< Default is to insert stores.
bool CustomRoots; //< Default is to pass through to backend.
+ bool CustomSafePoints; //< Default is to use NeededSafePoints
+ // to find safe points.
bool InitRoots; //< If set, roots are nulled during lowering.
bool UsesMetadata; //< If set, backend must emit metadata tables.
@@ -87,7 +90,9 @@ namespace llvm {
/// needsSafePoitns - True if safe points of any kind are required. By
// default, none are recorded.
- bool needsSafePoints() const { return NeededSafePoints != 0; }
+ bool needsSafePoints() const {
+ return CustomSafePoints || NeededSafePoints != 0;
+ }
/// needsSafePoint(Kind) - True if the given kind of safe point is
// required. By default, none are recorded.
@@ -109,6 +114,11 @@ namespace llvm {
/// can generate a stack map. If true, then
// performCustomLowering must delete them.
bool customRoots() const { return CustomRoots; }
+
+ /// customSafePoints - By default, the GC analysis will find safe
+ /// points according to NeededSafePoints. If true,
+ /// then findCustomSafePoints must create them.
+ bool customSafePoints() const { return CustomSafePoints; }
/// initializeRoots - If set, gcroot intrinsics should initialize their
// allocas to null before the first use. This is
@@ -135,6 +145,7 @@ namespace llvm {
/// which the LLVM IR can be modified.
virtual bool initializeCustomLowering(Module &F);
virtual bool performCustomLowering(Function &F);
+ virtual bool findCustomSafePoints(GCFunctionInfo& FI, MachineFunction& MF);
};
}
diff --git a/include/llvm/CodeGen/ISDOpcodes.h b/include/llvm/CodeGen/ISDOpcodes.h
index 184e96d..cb990ed 100644
--- a/include/llvm/CodeGen/ISDOpcodes.h
+++ b/include/llvm/CodeGen/ISDOpcodes.h
@@ -107,13 +107,6 @@ namespace ISD {
// and returns an outchain.
EH_SJLJ_LONGJMP,
- // OUTCHAIN = EH_SJLJ_DISPATCHSETUP(INCHAIN, setjmpval)
- // This corresponds to the eh.sjlj.dispatchsetup intrinsic. It takes an
- // input chain and the value returning from setjmp as inputs and returns an
- // outchain. By default, this does nothing. Targets can lower this to unwind
- // setup code if needed.
- EH_SJLJ_DISPATCHSETUP,
-
// TargetConstant* - Like Constant*, but the DAG does not do any folding,
// simplification, or lowering of the constant. They are used for constants
// which are known to fit in the immediate fields of their users, or for
@@ -319,6 +312,9 @@ namespace ISD {
/// Byte Swap and Counting operators.
BSWAP, CTTZ, CTLZ, CTPOP,
+ /// Bit counting operators with an undefined result for zero inputs.
+ CTTZ_ZERO_UNDEF, CTLZ_ZERO_UNDEF,
+
// Select(COND, TRUEVAL, FALSEVAL). If the type of the boolean COND is not
// i1 then the high bits must conform to getBooleanContents.
SELECT,
diff --git a/include/llvm/CodeGen/LinkAllCodegenComponents.h b/include/llvm/CodeGen/LinkAllCodegenComponents.h
index 098dd0b..a379a30 100644
--- a/include/llvm/CodeGen/LinkAllCodegenComponents.h
+++ b/include/llvm/CodeGen/LinkAllCodegenComponents.h
@@ -35,7 +35,6 @@ namespace {
(void) llvm::createFastRegisterAllocator();
(void) llvm::createBasicRegisterAllocator();
- (void) llvm::createLinearScanRegisterAllocator();
(void) llvm::createGreedyRegisterAllocator();
(void) llvm::createDefaultPBQPRegisterAllocator();
@@ -43,10 +42,8 @@ namespace {
llvm::linkShadowStackGC();
(void) llvm::createBURRListDAGScheduler(NULL, llvm::CodeGenOpt::Default);
- (void) llvm::createTDRRListDAGScheduler(NULL, llvm::CodeGenOpt::Default);
(void) llvm::createSourceListDAGScheduler(NULL,llvm::CodeGenOpt::Default);
(void) llvm::createHybridListDAGScheduler(NULL,llvm::CodeGenOpt::Default);
- (void) llvm::createTDListDAGScheduler(NULL, llvm::CodeGenOpt::Default);
(void) llvm::createFastDAGScheduler(NULL, llvm::CodeGenOpt::Default);
(void) llvm::createDefaultScheduler(NULL, llvm::CodeGenOpt::Default);
diff --git a/include/llvm/CodeGen/LiveInterval.h b/include/llvm/CodeGen/LiveInterval.h
index 2288c1a..f690243 100644
--- a/include/llvm/CodeGen/LiveInterval.h
+++ b/include/llvm/CodeGen/LiveInterval.h
@@ -381,7 +381,7 @@ namespace llvm {
/// point is not contained in the half-open live range. It is usually the
/// getDefIndex() slot following its last use.
bool killedAt(SlotIndex index) const {
- const_iterator r = find(index.getUseIndex());
+ const_iterator r = find(index.getRegSlot(true));
return r != end() && r->end == index;
}
diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h
index 8ca58b8..30537b4 100644
--- a/include/llvm/CodeGen/LiveIntervalAnalysis.h
+++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h
@@ -125,19 +125,6 @@ namespace llvm {
return (unsigned)(IntervalPercentage * indexes_->getFunctionSize());
}
- /// conflictsWithPhysReg - Returns true if the specified register is used or
- /// defined during the duration of the specified interval. Copies to and
- /// from li.reg are allowed. This method is only able to analyze simple
- /// ranges that stay within a single basic block. Anything else is
- /// considered a conflict.
- bool conflictsWithPhysReg(const LiveInterval &li, VirtRegMap &vrm,
- unsigned reg);
-
- /// conflictsWithAliasRef - Similar to conflictsWithPhysRegRef except
- /// it checks for alias uses and defs.
- bool conflictsWithAliasRef(LiveInterval &li, unsigned Reg,
- SmallPtrSet<MachineInstr*,32> &JoinedCopies);
-
// Interval creation
LiveInterval &getOrCreateInterval(unsigned reg) {
Reg2IntervalMap::iterator I = r2iMap_.find(reg);
@@ -271,20 +258,6 @@ namespace llvm {
/// print - Implement the dump method.
virtual void print(raw_ostream &O, const Module* = 0) const;
- /// addIntervalsForSpills - Create new intervals for spilled defs / uses of
- /// the given interval. FIXME: It also returns the weight of the spill slot
- /// (if any is created) by reference. This is temporary.
- std::vector<LiveInterval*>
- addIntervalsForSpills(const LiveInterval& i,
- const SmallVectorImpl<LiveInterval*> *SpillIs,
- const MachineLoopInfo *loopInfo, VirtRegMap& vrm);
-
- /// spillPhysRegAroundRegDefsUses - Spill the specified physical register
- /// around all defs and uses of the specified interval. Return true if it
- /// was able to cut its interval.
- bool spillPhysRegAroundRegDefsUses(const LiveInterval &li,
- unsigned PhysReg, VirtRegMap &vrm);
-
/// isReMaterializable - Returns true if every definition of MI of every
/// val# of the specified interval is re-materializable. Also returns true
/// by reference if all of the defs are load instructions.
@@ -292,20 +265,6 @@ namespace llvm {
const SmallVectorImpl<LiveInterval*> *SpillIs,
bool &isLoad);
- /// isReMaterializable - Returns true if the definition MI of the specified
- /// val# of the specified interval is re-materializable.
- bool isReMaterializable(const LiveInterval &li, const VNInfo *ValNo,
- MachineInstr *MI);
-
- /// getRepresentativeReg - Find the largest super register of the specified
- /// physical register.
- unsigned getRepresentativeReg(unsigned Reg) const;
-
- /// getNumConflictsWithPhysReg - Return the number of uses and defs of the
- /// specified interval that conflicts with the specified physical register.
- unsigned getNumConflictsWithPhysReg(const LiveInterval &li,
- unsigned PhysReg) const;
-
/// intervalIsInOneMBB - Returns true if the specified interval is entirely
/// within a single basic block.
bool intervalIsInOneMBB(const LiveInterval &li) const;
@@ -379,84 +338,6 @@ namespace llvm {
const SmallVectorImpl<LiveInterval*> *SpillIs,
bool &isLoad);
- /// tryFoldMemoryOperand - Attempts to fold either a spill / restore from
- /// slot / to reg or any rematerialized load into ith operand of specified
- /// MI. If it is successul, MI is updated with the newly created MI and
- /// returns true.
- bool tryFoldMemoryOperand(MachineInstr* &MI, VirtRegMap &vrm,
- MachineInstr *DefMI, SlotIndex InstrIdx,
- SmallVector<unsigned, 2> &Ops,
- bool isSS, int FrameIndex, unsigned Reg);
-
- /// canFoldMemoryOperand - Return true if the specified load / store
- /// folding is possible.
- bool canFoldMemoryOperand(MachineInstr *MI,
- SmallVector<unsigned, 2> &Ops,
- bool ReMatLoadSS) const;
-
- /// anyKillInMBBAfterIdx - Returns true if there is a kill of the specified
- /// VNInfo that's after the specified index but is within the basic block.
- bool anyKillInMBBAfterIdx(const LiveInterval &li, const VNInfo *VNI,
- MachineBasicBlock *MBB,
- SlotIndex Idx) const;
-
- /// hasAllocatableSuperReg - Return true if the specified physical register
- /// has any super register that's allocatable.
- bool hasAllocatableSuperReg(unsigned Reg) const;
-
- /// SRInfo - Spill / restore info.
- struct SRInfo {
- SlotIndex index;
- unsigned vreg;
- bool canFold;
- SRInfo(SlotIndex i, unsigned vr, bool f)
- : index(i), vreg(vr), canFold(f) {}
- };
-
- bool alsoFoldARestore(int Id, SlotIndex index, unsigned vr,
- BitVector &RestoreMBBs,
- DenseMap<unsigned,std::vector<SRInfo> >&RestoreIdxes);
- void eraseRestoreInfo(int Id, SlotIndex index, unsigned vr,
- BitVector &RestoreMBBs,
- DenseMap<unsigned,std::vector<SRInfo> >&RestoreIdxes);
-
- /// handleSpilledImpDefs - Remove IMPLICIT_DEF instructions which are being
- /// spilled and create empty intervals for their uses.
- void handleSpilledImpDefs(const LiveInterval &li, VirtRegMap &vrm,
- const TargetRegisterClass* rc,
- std::vector<LiveInterval*> &NewLIs);
-
- /// rewriteImplicitOps - Rewrite implicit use operands of MI (i.e. uses of
- /// interval on to-be re-materialized operands of MI) with new register.
- void rewriteImplicitOps(const LiveInterval &li,
- MachineInstr *MI, unsigned NewVReg, VirtRegMap &vrm);
-
- /// rewriteInstructionForSpills, rewriteInstructionsForSpills - Helper
- /// functions for addIntervalsForSpills to rewrite uses / defs for the given
- /// live range.
- bool rewriteInstructionForSpills(const LiveInterval &li, const VNInfo *VNI,
- bool TrySplit, SlotIndex index, SlotIndex end,
- MachineInstr *MI, MachineInstr *OrigDefMI, MachineInstr *DefMI,
- unsigned Slot, int LdSlot,
- bool isLoad, bool isLoadSS, bool DefIsReMat, bool CanDelete,
- VirtRegMap &vrm, const TargetRegisterClass* rc,
- SmallVector<int, 4> &ReMatIds, const MachineLoopInfo *loopInfo,
- unsigned &NewVReg, unsigned ImpUse, bool &HasDef, bool &HasUse,
- DenseMap<unsigned,unsigned> &MBBVRegsMap,
- std::vector<LiveInterval*> &NewLIs);
- void rewriteInstructionsForSpills(const LiveInterval &li, bool TrySplit,
- LiveInterval::Ranges::const_iterator &I,
- MachineInstr *OrigDefMI, MachineInstr *DefMI, unsigned Slot, int LdSlot,
- bool isLoad, bool isLoadSS, bool DefIsReMat, bool CanDelete,
- VirtRegMap &vrm, const TargetRegisterClass* rc,
- SmallVector<int, 4> &ReMatIds, const MachineLoopInfo *loopInfo,
- BitVector &SpillMBBs,
- DenseMap<unsigned,std::vector<SRInfo> > &SpillIdxes,
- BitVector &RestoreMBBs,
- DenseMap<unsigned,std::vector<SRInfo> > &RestoreIdxes,
- DenseMap<unsigned,unsigned> &MBBVRegsMap,
- std::vector<LiveInterval*> &NewLIs);
-
static LiveInterval* createInterval(unsigned Reg);
void printInstrs(raw_ostream &O) const;
diff --git a/include/llvm/CodeGen/MachineBasicBlock.h b/include/llvm/CodeGen/MachineBasicBlock.h
index 5a20e95..10a32d3 100644
--- a/include/llvm/CodeGen/MachineBasicBlock.h
+++ b/include/llvm/CodeGen/MachineBasicBlock.h
@@ -84,8 +84,9 @@ class MachineBasicBlock : public ilist_node<MachineBasicBlock> {
/// Alignment - Alignment of the basic block. Zero if the basic block does
/// not need to be aligned.
+ /// The alignment is specified as log2(bytes).
unsigned Alignment;
-
+
/// IsLandingPad - Indicate that this basic block is entered via an
/// exception handler.
bool IsLandingPad;
@@ -128,10 +129,89 @@ public:
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 getInstrIterator() const {
+ return MII;
+ }
+ };
+
+ typedef Instructions::iterator instr_iterator;
+ typedef Instructions::const_iterator const_instr_iterator;
+ typedef std::reverse_iterator<instr_iterator> reverse_instr_iterator;
+ typedef
+ std::reverse_iterator<const_instr_iterator> const_reverse_instr_iterator;
+
+ typedef
+ bundle_iterator<MachineInstr,instr_iterator> iterator;
+ typedef
+ bundle_iterator<const MachineInstr,const_instr_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(); }
@@ -141,15 +221,53 @@ public:
const MachineInstr& front() const { return Insts.front(); }
const MachineInstr& back() const { return Insts.back(); }
+ instr_iterator instr_begin() { return Insts.begin(); }
+ const_instr_iterator instr_begin() const { return Insts.begin(); }
+ instr_iterator instr_end() { return Insts.end(); }
+ const_instr_iterator instr_end() const { return Insts.end(); }
+ reverse_instr_iterator instr_rbegin() { return Insts.rbegin(); }
+ const_reverse_instr_iterator instr_rbegin() const { return Insts.rbegin(); }
+ reverse_instr_iterator instr_rend () { return Insts.rend(); }
+ const_reverse_instr_iterator instr_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() {
+ instr_iterator II = instr_end();
+ if (II != instr_begin()) {
+ while (II->isInsideBundle())
+ --II;
+ }
+ return II;
+ }
+ const_iterator end() const {
+ const_instr_iterator II = instr_end();
+ if (II != instr_begin()) {
+ while (II->isInsideBundle())
+ --II;
+ }
+ return II;
+ }
+ reverse_iterator rbegin() {
+ reverse_instr_iterator II = instr_rbegin();
+ if (II != instr_rend()) {
+ while (II->isInsideBundle())
+ ++II;
+ }
+ return II;
+ }
+ const_reverse_iterator rbegin() const {
+ const_reverse_instr_iterator II = instr_rbegin();
+ if (II != instr_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;
@@ -219,10 +337,12 @@ public:
bool livein_empty() const { return LiveIns.empty(); }
/// getAlignment - Return alignment of the basic block.
+ /// The alignment is specified as log2(bytes).
///
unsigned getAlignment() const { return Alignment; }
/// setAlignment - Set alignment of the basic block.
+ /// The alignment is specified as log2(bytes).
///
void setAlignment(unsigned Align) { Alignment = Align; }
@@ -320,18 +440,16 @@ public:
/// 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();
- }
+ /// getFirstInstrTerminator - Same getFirstTerminator but it ignores bundles
+ /// and return an instr_iterator instead.
+ instr_iterator getFirstInstrTerminator();
/// 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
@@ -344,32 +462,82 @@ public:
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(instr_iterator I, IT S, IT E) {
+ Insts.insert(I, S, E);
+ }
+ instr_iterator insert(instr_iterator I, MachineInstr *M) {
+ return Insts.insert(I, M);
+ }
+ instr_iterator insertAfter(instr_iterator I, MachineInstr *M) {
return Insts.insertAfter(I, 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); }
- MachineInstr *remove(MachineInstr *I) { return Insts.remove(I); }
- void clear() { Insts.clear(); }
+ template<typename IT>
+ void insert(iterator I, IT S, IT E) {
+ Insts.insert(I.getInstrIterator(), S, E);
+ }
+ iterator insert(iterator I, MachineInstr *M) {
+ return Insts.insert(I.getInstrIterator(), M);
+ }
+ iterator insertAfter(iterator I, MachineInstr *M) {
+ return Insts.insertAfter(I.getInstrIterator(), M);
+ }
+
+ /// erase - Remove the specified element or range from the instruction list.
+ /// These functions delete any instructions removed.
+ ///
+ instr_iterator erase(instr_iterator I) {
+ return Insts.erase(I);
+ }
+ instr_iterator erase(instr_iterator I, instr_iterator E) {
+ return Insts.erase(I, E);
+ }
+ instr_iterator erase_instr(MachineInstr *I) {
+ instr_iterator MII(I);
+ return erase(MII);
+ }
+
+ iterator erase(iterator I);
+ iterator erase(iterator I, iterator E) {
+ return Insts.erase(I.getInstrIterator(), E.getInstrIterator());
+ }
+ iterator erase(MachineInstr *I) {
+ iterator MII(I);
+ return erase(MII);
+ }
+
+ /// remove - Remove the instruction from the instruction list. This function
+ /// does not delete the instruction. WARNING: Note, if the specified
+ /// instruction is a bundle this function will remove all the bundled
+ /// instructions as well. It is up to the caller to keep a list of the
+ /// bundled instructions and re-insert them if desired. This function is
+ /// *not recommended* for manipulating instructions with bundled. Use
+ /// splice instead.
+ MachineInstr *remove(MachineInstr *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(instr_iterator where, MachineBasicBlock *Other,
+ instr_iterator From) {
Insts.splice(where, Other->Insts, From);
}
+ void splice(iterator where, MachineBasicBlock *Other, iterator From);
/// 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(instr_iterator where, MachineBasicBlock *Other, instr_iterator From,
+ instr_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.getInstrIterator(), Other->Insts,
+ From.getInstrIterator(), To.getInstrIterator());
}
/// removeFromParent - This method unlinks 'this' from the containing
@@ -396,7 +564,10 @@ public:
/// 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(instr_iterator MBBI);
+ DebugLoc findDebugLoc(iterator MBBI) {
+ return findDebugLoc(MBBI.getInstrIterator());
+ }
// Debugging methods.
void dump() const;
diff --git a/include/llvm/CodeGen/MachineBlockFrequencyInfo.h b/include/llvm/CodeGen/MachineBlockFrequencyInfo.h
index 416d40b..3d9d196 100644
--- a/include/llvm/CodeGen/MachineBlockFrequencyInfo.h
+++ b/include/llvm/CodeGen/MachineBlockFrequencyInfo.h
@@ -20,6 +20,7 @@
namespace llvm {
+class MachineBasicBlock;
class MachineBranchProbabilityInfo;
template<class BlockT, class FunctionT, class BranchProbInfoT>
class BlockFrequencyImpl;
@@ -28,7 +29,8 @@ class BlockFrequencyImpl;
/// machine basic block frequencies.
class MachineBlockFrequencyInfo : public MachineFunctionPass {
- BlockFrequencyImpl<MachineBasicBlock, MachineFunction, MachineBranchProbabilityInfo> *MBFI;
+ BlockFrequencyImpl<MachineBasicBlock, MachineFunction,
+ MachineBranchProbabilityInfo> *MBFI;
public:
static char ID;
diff --git a/include/llvm/CodeGen/MachineBranchProbabilityInfo.h b/include/llvm/CodeGen/MachineBranchProbabilityInfo.h
index d9673e2..e768874 100644
--- a/include/llvm/CodeGen/MachineBranchProbabilityInfo.h
+++ b/include/llvm/CodeGen/MachineBranchProbabilityInfo.h
@@ -34,9 +34,6 @@ class MachineBranchProbabilityInfo : public ImmutablePass {
// weight to just "inherit" the non-zero weight of an adjacent successor.
static const uint32_t DEFAULT_WEIGHT = 16;
- // Get sum of the block successors' weights.
- uint32_t getSumForBlock(MachineBasicBlock *MBB) const;
-
public:
static char ID;
@@ -53,15 +50,24 @@ public:
// DEFAULT_WEIGHT.
uint32_t getEdgeWeight(MachineBasicBlock *Src, MachineBasicBlock *Dst) const;
+ // Get sum of the block successors' weights, potentially scaling them to fit
+ // within 32-bits. If scaling is required, sets Scale based on the necessary
+ // adjustment. Any edge weights used with the sum should be divided by Scale.
+ uint32_t getSumForBlock(MachineBasicBlock *MBB, uint32_t &Scale) const;
+
// A 'Hot' edge is an edge which probability is >= 80%.
bool isEdgeHot(MachineBasicBlock *Src, MachineBasicBlock *Dst) const;
// Return a hot successor for the block BB or null if there isn't one.
+ // NB: This routine's complexity is linear on the number of successors.
MachineBasicBlock *getHotSucc(MachineBasicBlock *MBB) const;
// Return a probability as a fraction between 0 (0% probability) and
// 1 (100% probability), however the value is never equal to 0, and can be 1
// only iff SRC block has only one successor.
+ // NB: This routine's complexity is linear on the number of successors of
+ // Src. Querying sequentially for each successor's probability is a quadratic
+ // query pattern.
BranchProbability getEdgeProbability(MachineBasicBlock *Src,
MachineBasicBlock *Dst) const;
diff --git a/include/llvm/CodeGen/MachineFrameInfo.h b/include/llvm/CodeGen/MachineFrameInfo.h
index b347ca8..44402a9 100644
--- a/include/llvm/CodeGen/MachineFrameInfo.h
+++ b/include/llvm/CodeGen/MachineFrameInfo.h
@@ -465,7 +465,7 @@ public:
bool isSpillSlotObjectIndex(int ObjectIdx) const {
assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() &&
"Invalid Object Idx!");
- return Objects[ObjectIdx+NumFixedObjects].isSpillSlot;;
+ return Objects[ObjectIdx+NumFixedObjects].isSpillSlot;
}
/// isDeadObjectIndex - Returns true if the specified index corresponds to
diff --git a/include/llvm/CodeGen/MachineFunction.h b/include/llvm/CodeGen/MachineFunction.h
index 6e08f7b..3a4568a 100644
--- a/include/llvm/CodeGen/MachineFunction.h
+++ b/include/llvm/CodeGen/MachineFunction.h
@@ -187,7 +187,7 @@ public:
///
void setAlignment(unsigned A) { Alignment = A; }
- /// EnsureAlignment - Make sure the function is at least 'A' bits aligned.
+ /// EnsureAlignment - Make sure the function is at least 1 << A bytes aligned.
void EnsureAlignment(unsigned A) {
if (Alignment < A) Alignment = A;
}
@@ -437,6 +437,7 @@ template <> struct GraphTraits<MachineFunction*> :
typedef MachineFunction::iterator nodes_iterator;
static nodes_iterator nodes_begin(MachineFunction *F) { return F->begin(); }
static nodes_iterator nodes_end (MachineFunction *F) { return F->end(); }
+ static unsigned size (MachineFunction *F) { return F->size(); }
};
template <> struct GraphTraits<const MachineFunction*> :
public GraphTraits<const MachineBasicBlock*> {
@@ -452,6 +453,9 @@ template <> struct GraphTraits<const MachineFunction*> :
static nodes_iterator nodes_end (const MachineFunction *F) {
return F->end();
}
+ static unsigned size (const MachineFunction *F) {
+ return F->size();
+ }
};
diff --git a/include/llvm/CodeGen/MachineFunctionAnalysis.h b/include/llvm/CodeGen/MachineFunctionAnalysis.h
index 50676ad..50ea206 100644
--- a/include/llvm/CodeGen/MachineFunctionAnalysis.h
+++ b/include/llvm/CodeGen/MachineFunctionAnalysis.h
@@ -26,17 +26,14 @@ class MachineFunction;
struct MachineFunctionAnalysis : public FunctionPass {
private:
const TargetMachine &TM;
- CodeGenOpt::Level OptLevel;
MachineFunction *MF;
unsigned NextFnNum;
public:
static char ID;
- explicit MachineFunctionAnalysis(const TargetMachine &tm,
- CodeGenOpt::Level OL = CodeGenOpt::Default);
+ explicit MachineFunctionAnalysis(const TargetMachine &tm);
~MachineFunctionAnalysis();
MachineFunction &getMF() const { return *MF; }
- CodeGenOpt::Level getOptLevel() const { return OptLevel; }
virtual const char* getPassName() const {
return "Machine Function Analysis";
diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h
index cae38f3..904f1a6 100644
--- a/include/llvm/CodeGen/MachineInstr.h
+++ b/include/llvm/CodeGen/MachineInstr.h
@@ -53,9 +53,11 @@ public:
};
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.
@@ -148,6 +150,12 @@ public:
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;
@@ -167,10 +175,58 @@ public:
Flags = flags;
}
- /// clearAsmPrinterFlag - clear specific AsmPrinter flags
+ /// clearFlag - Clear a MI flag.
+ void clearFlag(MIFlag Flag) {
+ Flags &= ~((uint8_t)Flag);
+ }
+
+ /// 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);
+ }
+
+ /// setIsInsideBundle - Set InsideBundle bit.
+ ///
+ void setIsInsideBundle(bool Val = true) {
+ if (Val)
+ setFlag(InsideBundle);
+ else
+ clearFlag(InsideBundle);
}
/// getDebugLoc - Returns the debug location id of this MachineInstr.
@@ -232,6 +288,272 @@ public:
return MemRefsEnd - MemRefs == 1;
}
+ /// API for querying MachineInstr properties. They are the same as MCInstrDesc
+ /// queries but they are bundle aware.
+
+ enum QueryType {
+ IgnoreBundle, // Ignore bundles
+ AnyInBundle, // Return true if any instruction in bundle has property
+ AllInBundle // Return true if all instructions in bundle have property
+ };
+
+ /// hasProperty - Return true if the instruction (or in the case of a bundle,
+ /// the instructions inside the bundle) has the specified property.
+ /// The first argument is the property being queried.
+ /// The second argument indicates whether the query should look inside
+ /// instruction bundles.
+ /// If the third argument is true, than the query can return true when *any*
+ /// of the bundled instructions has the queried property. If it's false, then
+ /// this can return true iff *all* of the instructions have the property.
+ bool hasProperty(unsigned Flag, QueryType Type = AnyInBundle) const;
+
+ /// 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
+ /// present).
+ bool isVariadic(QueryType Type = IgnoreBundle) const {
+ return hasProperty(MCID::Variadic, Type);
+ }
+
+ /// hasOptionalDef - Set if this instruction has an optional definition, e.g.
+ /// ARM instructions which can set condition code if 's' bit is set.
+ bool hasOptionalDef(QueryType Type = IgnoreBundle) const {
+ return hasProperty(MCID::HasOptionalDef, Type);
+ }
+
+ /// isPseudo - Return true if this is a pseudo instruction that doesn't
+ /// correspond to a real machine instruction.
+ ///
+ bool isPseudo(QueryType Type = IgnoreBundle) const {
+ return hasProperty(MCID::Pseudo, Type);
+ }
+
+ bool isReturn(QueryType Type = AnyInBundle) const {
+ return hasProperty(MCID::Return, Type);
+ }
+
+ bool isCall(QueryType Type = AnyInBundle) const {
+ return hasProperty(MCID::Call, Type);
+ }
+
+ /// isBarrier - Returns true if the specified instruction stops control flow
+ /// from executing the instruction immediately following it. Examples include
+ /// unconditional branches and return instructions.
+ bool isBarrier(QueryType Type = AnyInBundle) const {
+ return hasProperty(MCID::Barrier, Type);
+ }
+
+ /// isTerminator - Returns true if this instruction part of the terminator for
+ /// a basic block. Typically this is things like return and branch
+ /// instructions.
+ ///
+ /// Various passes use this to insert code into the bottom of a basic block,
+ /// but before control flow occurs.
+ bool isTerminator(QueryType Type = AnyInBundle) const {
+ return hasProperty(MCID::Terminator, Type);
+ }
+
+ /// isBranch - Returns true if this is a conditional, unconditional, or
+ /// indirect branch. Predicates below can be used to discriminate between
+ /// these cases, and the TargetInstrInfo::AnalyzeBranch method can be used to
+ /// get more information.
+ bool isBranch(QueryType Type = AnyInBundle) const {
+ return hasProperty(MCID::Branch, Type);
+ }
+
+ /// isIndirectBranch - Return true if this is an indirect branch, such as a
+ /// branch through a register.
+ bool isIndirectBranch(QueryType Type = AnyInBundle) const {
+ return hasProperty(MCID::IndirectBranch, Type);
+ }
+
+ /// isConditionalBranch - Return true if this is a branch which may fall
+ /// through to the next instruction or may transfer control flow to some other
+ /// block. The TargetInstrInfo::AnalyzeBranch method can be used to get more
+ /// information about this branch.
+ bool isConditionalBranch(QueryType Type = AnyInBundle) const {
+ return isBranch(Type) & !isBarrier(Type) & !isIndirectBranch(Type);
+ }
+
+ /// isUnconditionalBranch - Return true if this is a branch which always
+ /// transfers control flow to some other block. The
+ /// TargetInstrInfo::AnalyzeBranch method can be used to get more information
+ /// about this branch.
+ bool isUnconditionalBranch(QueryType Type = AnyInBundle) const {
+ return isBranch(Type) & isBarrier(Type) & !isIndirectBranch(Type);
+ }
+
+ // isPredicable - Return true if this instruction has a predicate operand that
+ // controls execution. It may be set to 'always', or may be set to other
+ /// values. There are various methods in TargetInstrInfo that can be used to
+ /// control and modify the predicate in this instruction.
+ bool isPredicable(QueryType Type = AllInBundle) const {
+ // If it's a bundle than all bundled instructions must be predicable for this
+ // to return true.
+ return hasProperty(MCID::Predicable, Type);
+ }
+
+ /// isCompare - Return true if this instruction is a comparison.
+ bool isCompare(QueryType Type = IgnoreBundle) const {
+ return hasProperty(MCID::Compare, Type);
+ }
+
+ /// isMoveImmediate - Return true if this instruction is a move immediate
+ /// (including conditional moves) instruction.
+ bool isMoveImmediate(QueryType Type = IgnoreBundle) const {
+ return hasProperty(MCID::MoveImm, Type);
+ }
+
+ /// isBitcast - Return true if this instruction is a bitcast instruction.
+ ///
+ bool isBitcast(QueryType Type = IgnoreBundle) const {
+ return hasProperty(MCID::Bitcast, Type);
+ }
+
+ /// isNotDuplicable - Return true if this instruction cannot be safely
+ /// duplicated. For example, if the instruction has a unique labels attached
+ /// to it, duplicating it would cause multiple definition errors.
+ bool isNotDuplicable(QueryType Type = AnyInBundle) const {
+ return hasProperty(MCID::NotDuplicable, Type);
+ }
+
+ /// hasDelaySlot - Returns true if the specified instruction has a delay slot
+ /// which must be filled by the code generator.
+ bool hasDelaySlot(QueryType Type = AnyInBundle) const {
+ return hasProperty(MCID::DelaySlot, Type);
+ }
+
+ /// canFoldAsLoad - Return true for instructions that can be folded as
+ /// memory operands in other instructions. The most common use for this
+ /// is instructions that are simple loads from memory that don't modify
+ /// the loaded value in any way, but it can also be used for instructions
+ /// that can be expressed as constant-pool loads, such as V_SETALLONES
+ /// on x86, to allow them to be folded when it is beneficial.
+ /// This should only be set on instructions that return a value in their
+ /// only virtual register definition.
+ bool canFoldAsLoad(QueryType Type = IgnoreBundle) const {
+ return hasProperty(MCID::FoldableAsLoad, Type);
+ }
+
+ //===--------------------------------------------------------------------===//
+ // Side Effect Analysis
+ //===--------------------------------------------------------------------===//
+
+ /// mayLoad - Return true if this instruction could possibly read memory.
+ /// Instructions with this flag set are not necessarily simple load
+ /// instructions, they may load a value and modify it, for example.
+ bool mayLoad(QueryType Type = AnyInBundle) const {
+ return hasProperty(MCID::MayLoad, Type);
+ }
+
+
+ /// mayStore - Return true if this instruction could possibly modify memory.
+ /// Instructions with this flag set are not necessarily simple store
+ /// instructions, they may store a modified value based on their operands, or
+ /// may not actually modify anything, for example.
+ bool mayStore(QueryType Type = AnyInBundle) const {
+ return hasProperty(MCID::MayStore, Type);
+ }
+
+ //===--------------------------------------------------------------------===//
+ // Flags that indicate whether an instruction can be modified by a method.
+ //===--------------------------------------------------------------------===//
+
+ /// isCommutable - Return true if this may be a 2- or 3-address
+ /// instruction (of the form "X = op Y, Z, ..."), which produces the same
+ /// result if Y and Z are exchanged. If this flag is set, then the
+ /// TargetInstrInfo::commuteInstruction method may be used to hack on the
+ /// instruction.
+ ///
+ /// Note that this flag may be set on instructions that are only commutable
+ /// sometimes. In these cases, the call to commuteInstruction will fail.
+ /// Also note that some instructions require non-trivial modification to
+ /// commute them.
+ bool isCommutable(QueryType Type = IgnoreBundle) const {
+ return hasProperty(MCID::Commutable, Type);
+ }
+
+ /// isConvertibleTo3Addr - Return true if this is a 2-address instruction
+ /// which can be changed into a 3-address instruction if needed. Doing this
+ /// transformation can be profitable in the register allocator, because it
+ /// means that the instruction can use a 2-address form if possible, but
+ /// degrade into a less efficient form if the source and dest register cannot
+ /// be assigned to the same register. For example, this allows the x86
+ /// backend to turn a "shl reg, 3" instruction into an LEA instruction, which
+ /// is the same speed as the shift but has bigger code size.
+ ///
+ /// If this returns true, then the target must implement the
+ /// TargetInstrInfo::convertToThreeAddress method for this instruction, which
+ /// is allowed to fail if the transformation isn't valid for this specific
+ /// instruction (e.g. shl reg, 4 on x86).
+ ///
+ bool isConvertibleTo3Addr(QueryType Type = IgnoreBundle) const {
+ return hasProperty(MCID::ConvertibleTo3Addr, Type);
+ }
+
+ /// usesCustomInsertionHook - Return true if this instruction requires
+ /// custom insertion support when the DAG scheduler is inserting it into a
+ /// machine basic block. If this is true for the instruction, it basically
+ /// means that it is a pseudo instruction used at SelectionDAG time that is
+ /// expanded out into magic code by the target when MachineInstrs are formed.
+ ///
+ /// If this is true, the TargetLoweringInfo::InsertAtEndOfBasicBlock method
+ /// is used to insert this into the MachineBasicBlock.
+ bool usesCustomInsertionHook(QueryType Type = IgnoreBundle) const {
+ return hasProperty(MCID::UsesCustomInserter, Type);
+ }
+
+ /// hasPostISelHook - Return true if this instruction requires *adjustment*
+ /// after instruction selection by calling a target hook. For example, this
+ /// can be used to fill in ARM 's' optional operand depending on whether
+ /// the conditional flag register is used.
+ bool hasPostISelHook(QueryType Type = IgnoreBundle) const {
+ return hasProperty(MCID::HasPostISelHook, Type);
+ }
+
+ /// isRematerializable - Returns true if this instruction is a candidate for
+ /// remat. This flag is deprecated, please don't use it anymore. If this
+ /// flag is set, the isReallyTriviallyReMaterializable() method is called to
+ /// verify the instruction is really rematable.
+ bool isRematerializable(QueryType Type = AllInBundle) const {
+ // It's only possible to re-mat a bundle if all bundled instructions are
+ // re-materializable.
+ return hasProperty(MCID::Rematerializable, Type);
+ }
+
+ /// isAsCheapAsAMove - Returns true if this instruction has the same cost (or
+ /// less) than a move instruction. This is useful during certain types of
+ /// optimizations (e.g., remat during two-address conversion or machine licm)
+ /// where we would like to remat or hoist the instruction, but not if it costs
+ /// more than moving the instruction into the appropriate register. Note, we
+ /// are not marking copies from and to the same register class with this flag.
+ bool isAsCheapAsAMove(QueryType Type = AllInBundle) const {
+ // Only returns true for a bundle if all bundled instructions are cheap.
+ // FIXME: This probably requires a target hook.
+ return hasProperty(MCID::CheapAsAMove, Type);
+ }
+
+ /// hasExtraSrcRegAllocReq - Returns true if this instruction source operands
+ /// have special register allocation requirements that are not captured by the
+ /// operand register classes. e.g. ARM::STRD's two source registers must be an
+ /// even / odd pair, ARM::STM registers have to be in ascending order.
+ /// Post-register allocation passes should not attempt to change allocations
+ /// for sources of instructions with this flag.
+ bool hasExtraSrcRegAllocReq(QueryType Type = AnyInBundle) const {
+ return hasProperty(MCID::ExtraSrcRegAllocReq, Type);
+ }
+
+ /// hasExtraDefRegAllocReq - Returns true if this instruction def operands
+ /// have special register allocation requirements that are not captured by the
+ /// operand register classes. e.g. ARM::LDRD's two def registers must be an
+ /// even / odd pair, ARM::LDM registers have to be in ascending order.
+ /// Post-register allocation passes should not attempt to change allocations
+ /// for definitions of instructions with this flag.
+ bool hasExtraDefRegAllocReq(QueryType Type = AnyInBundle) const {
+ return hasProperty(MCID::ExtraDefRegAllocReq, Type);
+ }
+
+
enum MICheckType {
CheckDefs, // Check all operands for equality
CheckKillDead, // Check all operands including kill / dead markers
@@ -281,6 +603,9 @@ public:
bool isRegSequence() const {
return getOpcode() == TargetOpcode::REG_SEQUENCE;
}
+ bool isBundle() const {
+ return getOpcode() == TargetOpcode::BUNDLE;
+ }
bool isCopy() const {
return getOpcode() == TargetOpcode::COPY;
}
@@ -300,6 +625,9 @@ public:
getOperand(0).getSubReg() == getOperand(1).getSubReg();
}
+ /// getBundleSize - Return the number of instructions inside the MI bundle.
+ unsigned getBundleSize() const;
+
/// readsRegister - Return true if the MachineInstr reads the specified
/// register. If TargetRegisterInfo is passed, then it also checks if there
/// is a read of a super-register.
diff --git a/include/llvm/CodeGen/MachineInstrBuilder.h b/include/llvm/CodeGen/MachineInstrBuilder.h
index b989027..8025642 100644
--- a/include/llvm/CodeGen/MachineInstrBuilder.h
+++ b/include/llvm/CodeGen/MachineInstrBuilder.h
@@ -209,6 +209,30 @@ inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
return MachineInstrBuilder(MI).addReg(DestReg, RegState::Define);
}
+inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
+ MachineBasicBlock::instr_iterator I,
+ DebugLoc DL,
+ const MCInstrDesc &MCID,
+ unsigned DestReg) {
+ MachineInstr *MI = BB.getParent()->CreateMachineInstr(MCID, DL);
+ BB.insert(I, MI);
+ return MachineInstrBuilder(MI).addReg(DestReg, RegState::Define);
+}
+
+inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
+ MachineInstr *I,
+ DebugLoc DL,
+ const MCInstrDesc &MCID,
+ unsigned DestReg) {
+ if (I->isInsideBundle()) {
+ MachineBasicBlock::instr_iterator MII = I;
+ return BuildMI(BB, MII, DL, MCID, DestReg);
+ }
+
+ MachineBasicBlock::iterator MII = I;
+ return BuildMI(BB, MII, DL, MCID, DestReg);
+}
+
/// BuildMI - This version of the builder inserts the newly-built
/// instruction before the given position in the given MachineBasicBlock, and
/// does NOT take a destination register.
@@ -222,6 +246,28 @@ inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
return MachineInstrBuilder(MI);
}
+inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
+ MachineBasicBlock::instr_iterator I,
+ DebugLoc DL,
+ const MCInstrDesc &MCID) {
+ MachineInstr *MI = BB.getParent()->CreateMachineInstr(MCID, DL);
+ BB.insert(I, MI);
+ return MachineInstrBuilder(MI);
+}
+
+inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB,
+ MachineInstr *I,
+ DebugLoc DL,
+ const MCInstrDesc &MCID) {
+ if (I->isInsideBundle()) {
+ MachineBasicBlock::instr_iterator MII = I;
+ return BuildMI(BB, MII, DL, MCID);
+ }
+
+ MachineBasicBlock::iterator MII = I;
+ return BuildMI(BB, MII, DL, MCID);
+}
+
/// BuildMI - This version of the builder inserts the newly-built
/// instruction at the end of the given MachineBasicBlock, and does NOT take a
/// destination register.
diff --git a/include/llvm/CodeGen/MachineInstrBundle.h b/include/llvm/CodeGen/MachineInstrBundle.h
new file mode 100644
index 0000000..8c150e6
--- /dev/null
+++ b/include/llvm/CodeGen/MachineInstrBundle.h
@@ -0,0 +1,34 @@
+//===-- CodeGen/MachineInstBundle.h - MI bundle utilities -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provide utility functions to manipulate machine instruction
+// bundles.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_MACHINEINSTRBUNDLE_H
+#define LLVM_CODEGEN_MACHINEINSTRBUNDLE_H
+
+#include "llvm/CodeGen/MachineBasicBlock.h"
+
+namespace llvm {
+
+/// FinalizeBundle - Finalize a machine instruction bundle which includes
+/// a sequence of instructions starting from FirstMI to LastMI (inclusive).
+/// This routine adds a BUNDLE instruction to represent the bundle, it adds
+/// IsInternalRead markers to MachineOperands which are defined inside the
+/// bundle, and it copies externally visible defs and uses to the BUNDLE
+/// instruction.
+void FinalizeBundle(MachineBasicBlock &MBB,
+ MachineBasicBlock::instr_iterator FirstMI,
+ MachineBasicBlock::instr_iterator LastMI);
+
+} // End llvm namespace
+
+#endif
diff --git a/include/llvm/CodeGen/MachineMemOperand.h b/include/llvm/CodeGen/MachineMemOperand.h
index 768ce47..eed4a76 100644
--- a/include/llvm/CodeGen/MachineMemOperand.h
+++ b/include/llvm/CodeGen/MachineMemOperand.h
@@ -22,6 +22,7 @@ namespace llvm {
class Value;
class FoldingSetNodeID;
+class MDNode;
class raw_ostream;
/// MachinePointerInfo - This class contains a discriminated union of
@@ -95,8 +96,10 @@ public:
MOVolatile = 4,
/// The memory access is non-temporal.
MONonTemporal = 8,
+ /// The memory access is invariant.
+ MOInvariant = 16,
// This is the number of bits we need to represent flags.
- MOMaxBits = 4
+ MOMaxBits = 5
};
/// MachineMemOperand - Construct an MachineMemOperand object with the
@@ -141,6 +144,7 @@ public:
bool isStore() const { return Flags & MOStore; }
bool isVolatile() const { return Flags & MOVolatile; }
bool isNonTemporal() const { return Flags & MONonTemporal; }
+ bool isInvariant() const { return Flags & MOInvariant; }
/// refineAlignment - Update this MachineMemOperand to reflect the alignment
/// of MMO, if it has a greater alignment. This must only be used when the
diff --git a/include/llvm/CodeGen/MachineOperand.h b/include/llvm/CodeGen/MachineOperand.h
index 5440a63..2a977de 100644
--- a/include/llvm/CodeGen/MachineOperand.h
+++ b/include/llvm/CodeGen/MachineOperand.h
@@ -102,6 +102,17 @@ private:
///
bool IsUndef : 1;
+ /// IsInternalRead - True if this operand reads a value that was defined
+ /// inside the same instruction or bundle. This flag can be set on both use
+ /// and def operands. On a sub-register def operand, it refers to the part
+ /// of the register that isn't written. On a full-register def operand, it
+ /// is a noop.
+ ///
+ /// When this flag is set, the instruction bundle must contain at least one
+ /// other def of the register. If multiple instructions in the bundle define
+ /// the register, the meaning is target-defined.
+ bool IsInternalRead : 1;
+
/// IsEarlyClobber - True if this MO_Register 'def' operand is written to
/// by the MachineInstr before all input registers are read. This is used to
/// model the GCC inline asm '&' constraint modifier.
@@ -258,6 +269,11 @@ public:
return IsUndef;
}
+ bool isInternalRead() const {
+ assert(isReg() && "Wrong MachineOperand accessor");
+ return IsInternalRead;
+ }
+
bool isEarlyClobber() const {
assert(isReg() && "Wrong MachineOperand accessor");
return IsEarlyClobber;
@@ -272,9 +288,12 @@ public:
/// register. A use operand with the <undef> flag set doesn't read its
/// register. A sub-register def implicitly reads the other parts of the
/// register being redefined unless the <undef> flag is set.
+ ///
+ /// This refers to reading the register value from before the current
+ /// instruction or bundle. Internal bundle reads are not included.
bool readsReg() const {
assert(isReg() && "Wrong MachineOperand accessor");
- return !isUndef() && (isUse() || getSubReg());
+ return !isUndef() && !isInternalRead() && (isUse() || getSubReg());
}
/// getNextOperandForReg - Return the next MachineOperand in the function that
@@ -343,6 +362,11 @@ public:
IsUndef = Val;
}
+ void setIsInternalRead(bool Val = true) {
+ assert(isReg() && "Wrong MachineOperand accessor");
+ IsInternalRead = Val;
+ }
+
void setIsEarlyClobber(bool Val = true) {
assert(isReg() && IsDef && "Wrong MachineOperand accessor");
IsEarlyClobber = Val;
@@ -498,6 +522,7 @@ public:
Op.IsKill = isKill;
Op.IsDead = isDead;
Op.IsUndef = isUndef;
+ Op.IsInternalRead = false;
Op.IsEarlyClobber = isEarlyClobber;
Op.IsDebug = isDebug;
Op.SmallContents.RegNo = Reg;
diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h
index 7a03ce9..b4f6cac 100644
--- a/include/llvm/CodeGen/Passes.h
+++ b/include/llvm/CodeGen/Passes.h
@@ -118,11 +118,6 @@ namespace llvm {
///
FunctionPass *createGreedyRegisterAllocator();
- /// LinearScanRegisterAllocation Pass - This pass implements the linear scan
- /// register allocation algorithm, a global register allocator.
- ///
- FunctionPass *createLinearScanRegisterAllocator();
-
/// PBQPRegisterAllocation Pass - This pass implements the Partitioned Boolean
/// Quadratic Prograaming (PBQP) based register allocator.
///
@@ -155,6 +150,15 @@ namespace llvm {
/// IfConverter Pass - This pass performs machine code if conversion.
FunctionPass *createIfConverterPass();
+ /// MachineBlockPlacement Pass - This pass places basic blocks based on branch
+ /// probabilities.
+ FunctionPass *createMachineBlockPlacementPass();
+
+ /// MachineBlockPlacementStats Pass - This pass collects statistics about the
+ /// basic block placement using branch probabilities and block frequency
+ /// information.
+ FunctionPass *createMachineBlockPlacementStatsPass();
+
/// Code Placement Pass - This pass optimize code placement and aligns loop
/// headers to target specific alignment boundary.
FunctionPass *createCodePlacementOptPass();
@@ -234,6 +238,10 @@ namespace llvm {
///
FunctionPass *createExecutionDependencyFixPass(const TargetRegisterClass *RC);
+ /// createUnpackMachineBundles - This pass unpack machine instruction bundles.
+ ///
+ FunctionPass *createUnpackMachineBundlesPass();
+
} // End llvm namespace
#endif
diff --git a/include/llvm/CodeGen/SchedulerRegistry.h b/include/llvm/CodeGen/SchedulerRegistry.h
index 96573dd..3af6fcf 100644
--- a/include/llvm/CodeGen/SchedulerRegistry.h
+++ b/include/llvm/CodeGen/SchedulerRegistry.h
@@ -68,11 +68,6 @@ public:
ScheduleDAGSDNodes *createBURRListDAGScheduler(SelectionDAGISel *IS,
CodeGenOpt::Level OptLevel);
-/// createTDRRListDAGScheduler - This creates a top down register usage
-/// reduction list scheduler.
-ScheduleDAGSDNodes *createTDRRListDAGScheduler(SelectionDAGISel *IS,
- CodeGenOpt::Level OptLevel);
-
/// createBURRListDAGScheduler - This creates a bottom up list scheduler that
/// schedules nodes in source code order when possible.
ScheduleDAGSDNodes *createSourceListDAGScheduler(SelectionDAGISel *IS,
@@ -91,10 +86,6 @@ ScheduleDAGSDNodes *createHybridListDAGScheduler(SelectionDAGISel *IS,
/// to reduce register pressure.
ScheduleDAGSDNodes *createILPListDAGScheduler(SelectionDAGISel *IS,
CodeGenOpt::Level);
-/// createTDListDAGScheduler - This creates a top-down list scheduler with
-/// a hazard recognizer.
-ScheduleDAGSDNodes *createTDListDAGScheduler(SelectionDAGISel *IS,
- CodeGenOpt::Level OptLevel);
/// createFastDAGScheduler - This creates a "fast" scheduler.
///
diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h
index 132983c..f637ea2 100644
--- a/include/llvm/CodeGen/SelectionDAG.h
+++ b/include/llvm/CodeGen/SelectionDAG.h
@@ -112,9 +112,10 @@ public:
};
enum CombineLevel {
- Unrestricted, // Combine may create illegal operations and illegal types.
- NoIllegalTypes, // Combine may create illegal operations but no illegal types.
- NoIllegalOperations // Combine may only create legal operations and types.
+ BeforeLegalizeTypes,
+ AfterLegalizeTypes,
+ AfterLegalizeVectorOps,
+ AfterLegalizeDAG
};
class SelectionDAG;
@@ -138,6 +139,7 @@ class SelectionDAG {
const TargetSelectionDAGInfo &TSI;
MachineFunction *MF;
LLVMContext *Context;
+ CodeGenOpt::Level OptLevel;
/// EntryNode - The starting token.
SDNode EntryNode;
@@ -186,7 +188,7 @@ class SelectionDAG {
SelectionDAG(const SelectionDAG&); // Do not implement.
public:
- explicit SelectionDAG(const TargetMachine &TM);
+ explicit SelectionDAG(const TargetMachine &TM, llvm::CodeGenOpt::Level);
~SelectionDAG();
/// init - Prepare this SelectionDAG to process code in the given
@@ -650,7 +652,7 @@ public:
///
SDValue getLoad(EVT VT, DebugLoc dl, SDValue Chain, SDValue Ptr,
MachinePointerInfo PtrInfo, bool isVolatile,
- bool isNonTemporal, unsigned Alignment,
+ bool isNonTemporal, bool isInvariant, unsigned Alignment,
const MDNode *TBAAInfo = 0);
SDValue getExtLoad(ISD::LoadExtType ExtType, DebugLoc dl, EVT VT,
SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo,
@@ -663,8 +665,8 @@ public:
EVT VT, DebugLoc dl,
SDValue Chain, SDValue Ptr, SDValue Offset,
MachinePointerInfo PtrInfo, EVT MemVT,
- bool isVolatile, bool isNonTemporal, unsigned Alignment,
- const MDNode *TBAAInfo = 0);
+ bool isVolatile, bool isNonTemporal, bool isInvariant,
+ unsigned Alignment, const MDNode *TBAAInfo = 0);
SDValue getLoad(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType,
EVT VT, DebugLoc dl,
SDValue Chain, SDValue Ptr, SDValue Offset,
@@ -1033,6 +1035,7 @@ private:
void *&InsertPos);
SDNode *FindModifiedNodeSlot(SDNode *N, const SDValue *Ops, unsigned NumOps,
void *&InsertPos);
+ SDNode *UpdadeDebugLocOnMergedSDNode(SDNode *N, DebugLoc loc);
void DeleteNodeNotInCSEMaps(SDNode *N);
void DeallocateNode(SDNode *N);
diff --git a/include/llvm/CodeGen/SelectionDAGISel.h b/include/llvm/CodeGen/SelectionDAGISel.h
index ecf3947..3c5c5df 100644
--- a/include/llvm/CodeGen/SelectionDAGISel.h
+++ b/include/llvm/CodeGen/SelectionDAGISel.h
@@ -29,6 +29,7 @@ namespace llvm {
class MachineFunction;
class MachineInstr;
class TargetLowering;
+ class TargetLibraryInfo;
class TargetInstrInfo;
class FunctionLoweringInfo;
class ScheduleHazardRecognizer;
@@ -42,6 +43,7 @@ class SelectionDAGISel : public MachineFunctionPass {
public:
const TargetMachine &TM;
const TargetLowering &TLI;
+ const TargetLibraryInfo *LibInfo;
FunctionLoweringInfo *FuncInfo;
MachineFunction *MF;
MachineRegisterInfo *RegInfo;
@@ -92,7 +94,7 @@ public:
/// IsLegalToFold - Returns true if the specific operand node N of
/// U can be folded during instruction selection that starts at Root.
- /// FIXME: This is a static member function because the MSP430/SystemZ/X86
+ /// FIXME: This is a static member function because the MSP430/X86
/// targets, which uses it during isel. This could become a proper member.
static bool IsLegalToFold(SDValue N, SDNode *U, SDNode *Root,
CodeGenOpt::Level OptLevel,
diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h
index 6c7be69..547dacb 100644
--- a/include/llvm/CodeGen/SelectionDAGNodes.h
+++ b/include/llvm/CodeGen/SelectionDAGNodes.h
@@ -917,12 +917,13 @@ public:
// with MachineMemOperand information.
bool isVolatile() const { return (SubclassData >> 5) & 1; }
bool isNonTemporal() const { return (SubclassData >> 6) & 1; }
+ bool isInvariant() const { return (SubclassData >> 7) & 1; }
AtomicOrdering getOrdering() const {
- return AtomicOrdering((SubclassData >> 7) & 15);
+ return AtomicOrdering((SubclassData >> 8) & 15);
}
SynchronizationScope getSynchScope() const {
- return SynchronizationScope((SubclassData >> 11) & 1);
+ return SynchronizationScope((SubclassData >> 12) & 1);
}
/// Returns the SrcValue and offset that describes the location of the access
@@ -993,8 +994,8 @@ class AtomicSDNode : public MemSDNode {
"Ordering may not require more than 4 bits!");
assert((SynchScope & 1) == SynchScope &&
"SynchScope may not require more than 1 bit!");
- SubclassData |= Ordering << 7;
- SubclassData |= SynchScope << 11;
+ SubclassData |= Ordering << 8;
+ SubclassData |= SynchScope << 12;
assert(getOrdering() == Ordering && "Ordering encoding error!");
assert(getSynchScope() == SynchScope && "Synch-scope encoding error!");
@@ -1684,6 +1685,8 @@ public:
/// setMemRefs - Assign this MachineSDNodes's memory reference descriptor
/// list. This does not transfer ownership.
void setMemRefs(mmo_iterator NewMemRefs, mmo_iterator NewMemRefsEnd) {
+ for (mmo_iterator MMI = NewMemRefs, MME = NewMemRefsEnd; MMI != MME; ++MMI)
+ assert(*MMI && "Null mem ref detected!");
MemRefs = NewMemRefs;
MemRefsEnd = NewMemRefsEnd;
}
diff --git a/include/llvm/CodeGen/SlotIndexes.h b/include/llvm/CodeGen/SlotIndexes.h
index 2d98864..cb2baa6 100644
--- a/include/llvm/CodeGen/SlotIndexes.h
+++ b/include/llvm/CodeGen/SlotIndexes.h
@@ -83,7 +83,29 @@ namespace llvm {
friend class SlotIndexes;
friend struct DenseMapInfo<SlotIndex>;
- enum Slot { LOAD, USE, DEF, STORE, NUM };
+ enum Slot {
+ /// Basic block boundary. Used for live ranges entering and leaving a
+ /// block without being live in the layout neighbor. Also used as the
+ /// def slot of PHI-defs.
+ Slot_Block,
+
+ /// Early-clobber register use/def slot. A live range defined at
+ /// Slot_EarlyCLobber interferes with normal live ranges killed at
+ /// Slot_Register. Also used as the kill slot for live ranges tied to an
+ /// early-clobber def.
+ Slot_EarlyClobber,
+
+ /// Normal register use/def slot. Normal instructions kill and define
+ /// register live ranges at this slot.
+ Slot_Register,
+
+ /// Dead def kill point. Kill slot for a live range that is defined by
+ /// the same instruction (Slot_Register or Slot_EarlyClobber), but isn't
+ /// used anywhere.
+ Slot_Dead,
+
+ Slot_Count
+ };
PointerIntPair<IndexListEntry*, 2, unsigned> lie;
@@ -113,7 +135,7 @@ namespace llvm {
enum {
/// The default distance between instructions as returned by distance().
/// This may vary as instructions are inserted and removed.
- InstrDist = 4*NUM
+ InstrDist = 4 * Slot_Count
};
static inline SlotIndex getEmptyKey() {
@@ -191,64 +213,44 @@ namespace llvm {
return other.getIndex() - getIndex();
}
- /// isLoad - Return true if this is a LOAD slot.
- bool isLoad() const {
- return getSlot() == LOAD;
- }
+ /// isBlock - Returns true if this is a block boundary slot.
+ bool isBlock() const { return getSlot() == Slot_Block; }
- /// isDef - Return true if this is a DEF slot.
- bool isDef() const {
- return getSlot() == DEF;
- }
+ /// isEarlyClobber - Returns true if this is an early-clobber slot.
+ bool isEarlyClobber() const { return getSlot() == Slot_EarlyClobber; }
- /// isUse - Return true if this is a USE slot.
- bool isUse() const {
- return getSlot() == USE;
- }
+ /// isRegister - Returns true if this is a normal register use/def slot.
+ /// Note that early-clobber slots may also be used for uses and defs.
+ bool isRegister() const { return getSlot() == Slot_Register; }
- /// isStore - Return true if this is a STORE slot.
- bool isStore() const {
- return getSlot() == STORE;
- }
+ /// isDead - Returns true if this is a dead def kill slot.
+ bool isDead() const { return getSlot() == Slot_Dead; }
/// Returns the base index for associated with this index. The base index
- /// is the one associated with the LOAD slot for the instruction pointed to
- /// by this index.
+ /// is the one associated with the Slot_Block slot for the instruction
+ /// pointed to by this index.
SlotIndex getBaseIndex() const {
- return getLoadIndex();
+ return SlotIndex(&entry(), Slot_Block);
}
/// Returns the boundary index for associated with this index. The boundary
- /// index is the one associated with the LOAD slot for the instruction
+ /// index is the one associated with the Slot_Block slot for the instruction
/// pointed to by this index.
SlotIndex getBoundaryIndex() const {
- return getStoreIndex();
+ return SlotIndex(&entry(), Slot_Dead);
}
- /// Returns the index of the LOAD slot for the instruction pointed to by
- /// this index.
- SlotIndex getLoadIndex() const {
- return SlotIndex(&entry(), SlotIndex::LOAD);
- }
-
- /// Returns the index of the USE slot for the instruction pointed to by
- /// this index.
- SlotIndex getUseIndex() const {
- return SlotIndex(&entry(), SlotIndex::USE);
+ /// Returns the register use/def slot in the current instruction for a
+ /// normal or early-clobber def.
+ SlotIndex getRegSlot(bool EC = false) const {
+ return SlotIndex(&entry(), EC ? Slot_EarlyClobber : Slot_Register);
}
- /// Returns the index of the DEF slot for the instruction pointed to by
- /// this index.
- SlotIndex getDefIndex() const {
- return SlotIndex(&entry(), SlotIndex::DEF);
+ /// Returns the dead def kill slot for the current instruction.
+ SlotIndex getDeadSlot() const {
+ return SlotIndex(&entry(), Slot_Dead);
}
- /// Returns the index of the STORE slot for the instruction pointed to by
- /// this index.
- SlotIndex getStoreIndex() const {
- return SlotIndex(&entry(), SlotIndex::STORE);
- }
-
/// Returns the next slot in the index list. This could be either the
/// next slot for the instruction pointed to by this index or, if this
/// index is a STORE, the first slot for the next instruction.
@@ -257,8 +259,8 @@ namespace llvm {
/// use one of those methods.
SlotIndex getNextSlot() const {
Slot s = getSlot();
- if (s == SlotIndex::STORE) {
- return SlotIndex(entry().getNext(), SlotIndex::LOAD);
+ if (s == Slot_Dead) {
+ return SlotIndex(entry().getNext(), Slot_Block);
}
return SlotIndex(&entry(), s + 1);
}
@@ -271,14 +273,14 @@ namespace llvm {
/// Returns the previous slot in the index list. This could be either the
/// previous slot for the instruction pointed to by this index or, if this
- /// index is a LOAD, the last slot for the previous instruction.
+ /// index is a Slot_Block, the last slot for the previous instruction.
/// WARNING: This method is considerably more expensive than the methods
/// that return specific slots (getUseIndex(), etc). If you can - please
/// use one of those methods.
SlotIndex getPrevSlot() const {
Slot s = getSlot();
- if (s == SlotIndex::LOAD) {
- return SlotIndex(entry().getPrev(), SlotIndex::STORE);
+ if (s == Slot_Block) {
+ return SlotIndex(entry().getPrev(), Slot_Dead);
}
return SlotIndex(&entry(), s - 1);
}
@@ -677,7 +679,7 @@ namespace llvm {
if (dist == 0)
renumberIndexes(newEntry);
- SlotIndex newIndex(newEntry, SlotIndex::LOAD);
+ SlotIndex newIndex(newEntry, SlotIndex::Slot_Block);
mi2iMap.insert(std::make_pair(mi, newIndex));
return newIndex;
}
@@ -728,8 +730,8 @@ namespace llvm {
insert(nextEntry, startEntry);
insert(nextEntry, stopEntry);
- SlotIndex startIdx(startEntry, SlotIndex::LOAD);
- SlotIndex endIdx(nextEntry, SlotIndex::LOAD);
+ SlotIndex startIdx(startEntry, SlotIndex::Slot_Block);
+ SlotIndex endIdx(nextEntry, SlotIndex::Slot_Block);
assert(unsigned(mbb->getNumber()) == MBBRanges.size() &&
"Blocks must be added in order");
diff --git a/include/llvm/CodeGen/ValueTypes.h b/include/llvm/CodeGen/ValueTypes.h
index cae0bcb..7a7080f 100644
--- a/include/llvm/CodeGen/ValueTypes.h
+++ b/include/llvm/CodeGen/ValueTypes.h
@@ -83,7 +83,7 @@ namespace llvm {
isVoid = 35, // This has no value
- untyped = 36, // This value takes a register, but has
+ Untyped = 36, // This value takes a register, but has
// unspecified type. The register class
// will be determined by the opcode.