#define LLVM_CODEGEN_SIMPLE_REGISTER_COALESCING_H
#include "llvm/CodeGen/MachineFunctionPass.h"
-#include "llvm/CodeGen/LiveInterval.h"
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
#include "llvm/CodeGen/RegisterCoalescer.h"
#include "llvm/ADT/BitVector.h"
-#include "llvm/ADT/IndexedMap.h"
#include <queue>
namespace llvm {
const TargetRegisterInfo* tri_;
const TargetInstrInfo* tii_;
LiveIntervals *li_;
- LiveVariables *lv_;
const MachineLoopInfo* loopInfo;
BitVector allocatableRegs_;
///
SmallPtrSet<MachineInstr*, 32> JoinedCopies;
+ /// ReMatCopies - Keep track of copies eliminated due to remat.
+ ///
+ SmallPtrSet<MachineInstr*, 32> ReMatCopies;
+
+ /// ReMatDefs - Keep track of definition instructions which have
+ /// been remat'ed.
+ SmallPtrSet<MachineInstr*, 8> ReMatDefs;
+
public:
static char ID; // Pass identifcation, replacement for typeid
- SimpleRegisterCoalescing() : MachineFunctionPass((intptr_t)&ID) {}
+ SimpleRegisterCoalescing() : MachineFunctionPass(&ID) {}
struct InstrSlots {
enum {
unsigned getRepIntervalSize(unsigned Reg) {
if (!li_->hasInterval(Reg))
return 0;
- return li_->getInterval(Reg).getSize();
+ return li_->getApproximateInstructionCount(li_->getInterval(Reg)) *
+ LiveIntervals::InstrSlots::NUM;
}
/// print - Implement the dump method.
/// joins them and returns true.
bool SimpleJoin(LiveInterval &LHS, LiveInterval &RHS);
- /// Return true if the two specified registers belong to different
- /// register classes. The registers may be either phys or virt regs.
+ /// Return true if the two specified registers belong to different register
+ /// classes. The registers may be either phys or virt regs.
bool differingRegisterClasses(unsigned RegA, unsigned RegB) const;
bool RemoveCopyByCommutingDef(LiveInterval &IntA, LiveInterval &IntB,
MachineInstr *CopyMI);
+ /// TrimLiveIntervalToLastUse - If there is a last use in the same basic
+ /// block as the copy instruction, trim the ive interval to the last use
+ /// and return true.
+ bool TrimLiveIntervalToLastUse(unsigned CopyIdx,
+ MachineBasicBlock *CopyMBB,
+ LiveInterval &li, const LiveRange *LR);
+
+ /// ReMaterializeTrivialDef - If the source of a copy is defined by a trivial
+ /// computation, replace the copy by rematerialize the definition.
+ bool ReMaterializeTrivialDef(LiveInterval &SrcInt, unsigned DstReg,
+ MachineInstr *CopyMI);
+
/// TurnCopyIntoImpDef - If source of the specified copy is an implicit def,
/// turn the copy into an implicit def.
bool TurnCopyIntoImpDef(MachineBasicBlock::iterator &I,
MachineBasicBlock *MBB,
unsigned DstReg, unsigned SrcReg);
- /// isBackEdgeCopy - Returns true if CopyMI is a back edge copy.
+ /// CanCoalesceWithImpDef - Returns true if the specified copy instruction
+ /// from an implicit def to another register can be coalesced away.
+ bool CanCoalesceWithImpDef(MachineInstr *CopyMI,
+ LiveInterval &li, LiveInterval &ImpLi) const;
+
+ /// RemoveCopiesFromValNo - The specified value# is defined by an implicit
+ /// def and it is being removed. Turn all copies from this value# into
+ /// identity copies so they will be removed.
+ void RemoveCopiesFromValNo(LiveInterval &li, VNInfo *VNI);
+
+ /// isWinToJoinVRWithSrcPhysReg - Return true if it's worth while to join a
+ /// a virtual destination register with physical source register.
+ bool isWinToJoinVRWithSrcPhysReg(MachineInstr *CopyMI,
+ MachineBasicBlock *CopyMBB,
+ LiveInterval &DstInt, LiveInterval &SrcInt);
+
+ /// isWinToJoinVRWithDstPhysReg - Return true if it's worth while to join a
+ /// copy from a virtual source register to a physical destination register.
+ bool isWinToJoinVRWithDstPhysReg(MachineInstr *CopyMI,
+ MachineBasicBlock *CopyMBB,
+ LiveInterval &DstInt, LiveInterval &SrcInt);
+
+ /// isWinToJoinCrossClass - Return true if it's profitable to coalesce
+ /// two virtual registers from different register classes.
+ bool isWinToJoinCrossClass(unsigned LargeReg, unsigned SmallReg,
+ unsigned Threshold);
+
+ /// HasIncompatibleSubRegDefUse - If we are trying to coalesce a virtual
+ /// register with a physical register, check if any of the virtual register
+ /// operand is a sub-register use or def. If so, make sure it won't result
+ /// in an illegal extract_subreg or insert_subreg instruction.
+ bool HasIncompatibleSubRegDefUse(MachineInstr *CopyMI,
+ unsigned VirtReg, unsigned PhysReg);
+
+ /// CanJoinExtractSubRegToPhysReg - Return true if it's possible to coalesce
+ /// an extract_subreg where dst is a physical register, e.g.
+ /// cl = EXTRACT_SUBREG reg1024, 1
+ bool CanJoinExtractSubRegToPhysReg(unsigned DstReg, unsigned SrcReg,
+ unsigned SubIdx, unsigned &RealDstReg);
+
+ /// CanJoinInsertSubRegToPhysReg - Return true if it's possible to coalesce
+ /// an insert_subreg where src is a physical register, e.g.
+ /// reg1024 = INSERT_SUBREG reg1024, c1, 0
+ bool CanJoinInsertSubRegToPhysReg(unsigned DstReg, unsigned SrcReg,
+ unsigned SubIdx, unsigned &RealDstReg);
+
+ /// RangeIsDefinedByCopyFromReg - Return true if the specified live range of
+ /// the specified live interval is defined by a copy from the specified
+ /// register.
+ bool RangeIsDefinedByCopyFromReg(LiveInterval &li, LiveRange *LR,
+ unsigned Reg);
+
+ /// isBackEdgeCopy - Return true if CopyMI is a back edge copy.
///
- bool isBackEdgeCopy(MachineInstr *CopyMI, unsigned DstReg);
+ bool isBackEdgeCopy(MachineInstr *CopyMI, unsigned DstReg) const;
/// UpdateRegDefsUses - Replace all defs and uses of SrcReg to DstReg and
/// update the subregister number if it is not zero. If DstReg is a
/// subregister.
void UpdateRegDefsUses(unsigned SrcReg, unsigned DstReg, unsigned SubIdx);
+ /// RemoveDeadImpDef - Remove implicit_def instructions which are
+ /// "re-defining" registers due to insert_subreg coalescing. e.g.
+ void RemoveDeadImpDef(unsigned Reg, LiveInterval &LI);
+
/// RemoveUnnecessaryKills - Remove kill markers that are no longer accurate
/// due to live range lengthening as the result of coalescing.
void RemoveUnnecessaryKills(unsigned Reg, LiveInterval &LI);
/// ShortenDeadCopyLiveRange - Shorten a live range defined by a dead copy.
- ///
- void ShortenDeadCopyLiveRange(LiveInterval &li, MachineInstr *CopyMI);
+ /// Return true if live interval is removed.
+ bool ShortenDeadCopyLiveRange(LiveInterval &li, MachineInstr *CopyMI);
/// ShortenDeadCopyLiveRange - Shorten a live range as it's artificially
/// extended by a dead copy. Mark the last use (if any) of the val# as kill
/// as ends the live range there. If there isn't another use, then this
- /// live range is dead.
- void ShortenDeadCopySrcLiveRange(LiveInterval &li, MachineInstr *CopyMI);
+ /// live range is dead. Return true if live interval is removed.
+ bool ShortenDeadCopySrcLiveRange(LiveInterval &li, MachineInstr *CopyMI);
+
+ /// RemoveDeadDef - If a def of a live interval is now determined dead,
+ /// remove the val# it defines. If the live interval becomes empty, remove
+ /// it as well.
+ bool RemoveDeadDef(LiveInterval &li, MachineInstr *DefMI);
/// lastRegisterUse - Returns the last use of the specific register between
/// cycles Start and End or NULL if there are no uses.