#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallVector.h"
#include <map>
namespace llvm {
class LiveVariables : public MachineFunctionPass {
public:
+ static char ID; // Pass identification, replacement for typeid
+ LiveVariables() : MachineFunctionPass((intptr_t)&ID) {}
+
/// VarInfo - This represents the regions where a virtual register is live in
/// the program. We represent this with three different pieces of
/// information: the instruction that uniquely defines the value, the set of
///
BitVector AliveBlocks;
+ /// UsedBlocks - Set of blocks of which this value is actually used. This
+ /// is a bit set which uses the basic block number as an index.
+ BitVector UsedBlocks;
+
+ /// NumUses - Number of uses of this register across the entire function.
+ ///
+ unsigned NumUses;
+
/// Kills - List of MachineInstruction's which are the last use of this
/// virtual register (kill it) in their basic block.
///
std::vector<MachineInstr*> Kills;
- VarInfo() : DefInst(0) {}
+ VarInfo() : DefInst(0), NumUses(0) {}
/// removeKill - Delete a kill corresponding to the specified
/// machine instruction. Returns true if there was a kill
///
std::vector<VarInfo> VirtRegInfo;
- /// AllocatablePhysicalRegisters - This vector keeps track of which registers
- /// are actually register allocatable by the target machine. We can not track
- /// liveness for values that are not in this set.
+ /// ReservedRegisters - This vector keeps track of which registers
+ /// are reserved register which are not allocatable by the target machine.
+ /// We can not track liveness for values that are in this set.
///
- BitVector AllocatablePhysicalRegisters;
+ BitVector ReservedRegisters;
private: // Intermediate data structures
+ MachineFunction *MF;
+
const MRegisterInfo *RegInfo;
+ // PhysRegInfo - Keep track of which instruction was the last def/use of a
+ // physical register. This is a purely local property, because all physical
+ // register references as presumed dead across basic blocks.
MachineInstr **PhysRegInfo;
+
+ // PhysRegUsed - Keep track whether the physical register has been used after
+ // its last definition. This is local property.
bool *PhysRegUsed;
- typedef std::map<const MachineBasicBlock*,
- std::vector<unsigned> > PHIVarInfoMap;
+ // PhysRegPartUse - Keep track of which instruction was the last partial use
+ // of a physical register (e.g. on X86 a def of EAX followed by a use of AX).
+ // This is a purely local property.
+ MachineInstr **PhysRegPartUse;
- PHIVarInfoMap PHIVarInfo;
+ // PhysRegPartDef - Keep track of a list of instructions which "partially"
+ // defined the physical register (e.g. on X86 AX partially defines EAX).
+ // These are turned into use/mod/write if there is a use of the register
+ // later in the same block. This is local property.
+ SmallVector<MachineInstr*, 4> *PhysRegPartDef;
+ SmallVector<unsigned, 4> *PHIVarInfo;
/// addRegisterKilled - We have determined MI kills a register. Look for the
- /// operand that uses it and mark it as IsKill.
- void addRegisterKilled(unsigned IncomingReg, MachineInstr *MI);
+ /// operand that uses it and mark it as IsKill. If AddIfNotFound is true,
+ /// add a implicit operand if it's not found. Returns true if the operand
+ /// exists / is added.
+ bool addRegisterKilled(unsigned IncomingReg, MachineInstr *MI,
+ bool AddIfNotFound = false);
/// addRegisterDead - We have determined MI defined a register without a use.
- /// Look for the operand that defines it and mark it as IsDead.
- void addRegisterDead(unsigned IncomingReg, MachineInstr *MI);
-
+ /// Look for the operand that defines it and mark it as IsDead. If
+ /// AddIfNotFound is true, add a implicit operand if it's not found. Returns
+ /// true if the operand exists / is added.
+ bool addRegisterDead(unsigned IncomingReg, MachineInstr *MI,
+ bool AddIfNotFound = false);
+
+ void addRegisterKills(unsigned Reg, MachineInstr *MI,
+ SmallSet<unsigned, 4> &SubKills);
+
+ /// HandlePhysRegKill - Add kills of Reg and its sub-registers to the
+ /// uses. Pay special attention to the sub-register uses which may come below
+ /// the last use of the whole register.
+ bool HandlePhysRegKill(unsigned Reg, MachineInstr *MI,
+ SmallSet<unsigned, 4> &SubKills);
+ bool HandlePhysRegKill(unsigned Reg, MachineInstr *MI);
void HandlePhysRegUse(unsigned Reg, MachineInstr *MI);
void HandlePhysRegDef(unsigned Reg, MachineInstr *MI);
/// addVirtualRegisterKilled - Add information about the fact that the
/// specified register is killed after being used by the specified
- /// instruction.
- ///
- void addVirtualRegisterKilled(unsigned IncomingReg, MachineInstr *MI) {
- addRegisterKilled(IncomingReg, MI);
- getVarInfo(IncomingReg).Kills.push_back(MI);
+ /// instruction. If AddIfNotFound is true, add a implicit operand if it's
+ /// not found.
+ void addVirtualRegisterKilled(unsigned IncomingReg, MachineInstr *MI,
+ bool AddIfNotFound = false) {
+ if (addRegisterKilled(IncomingReg, MI, AddIfNotFound))
+ getVarInfo(IncomingReg).Kills.push_back(MI);
}
/// removeVirtualRegisterKilled - Remove the specified virtual
bool Removed = false;
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
MachineOperand &MO = MI->getOperand(i);
- if (MO.isReg() && MO.isUse() && MO.getReg() == reg) {
+ if (MO.isRegister() && MO.isKill() && MO.getReg() == reg) {
MO.unsetIsKill();
Removed = true;
break;
void removeVirtualRegistersKilled(MachineInstr *MI);
/// addVirtualRegisterDead - Add information about the fact that the specified
- /// register is dead after being used by the specified instruction.
- ///
- void addVirtualRegisterDead(unsigned IncomingReg, MachineInstr *MI) {
- addRegisterDead(IncomingReg, MI);
- getVarInfo(IncomingReg).Kills.push_back(MI);
+ /// register is dead after being used by the specified instruction. If
+ /// AddIfNotFound is true, add a implicit operand if it's not found.
+ void addVirtualRegisterDead(unsigned IncomingReg, MachineInstr *MI,
+ bool AddIfNotFound = false) {
+ if (addRegisterDead(IncomingReg, MI, AddIfNotFound))
+ getVarInfo(IncomingReg).Kills.push_back(MI);
}
/// removeVirtualRegisterDead - Remove the specified virtual
bool Removed = false;
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
MachineOperand &MO = MI->getOperand(i);
- if (MO.isReg() && MO.isDef() && MO.getReg() == reg) {
+ if (MO.isRegister() && MO.isDef() && MO.getReg() == reg) {
MO.unsetIsDead();
Removed = true;
break;
VarInfo &getVarInfo(unsigned RegIdx);
void MarkVirtRegAliveInBlock(VarInfo &VRInfo, MachineBasicBlock *BB);
+ void MarkVirtRegAliveInBlock(VarInfo &VRInfo, MachineBasicBlock *BB,
+ std::vector<MachineBasicBlock*> &WorkList);
void HandleVirtRegUse(VarInfo &VRInfo, MachineBasicBlock *MBB,
MachineInstr *MI);
};