aboutsummaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/TwoAddressInstructionPass.cpp
diff options
context:
space:
mode:
authorevancheng <evancheng@91177308-0d34-0410-b5e6-96231b3b80d8>2009-01-25 03:53:59 +0000
committerevancheng <evancheng@91177308-0d34-0410-b5e6-96231b3b80d8>2009-01-25 03:53:59 +0000
commit58d5ef24fd6c26a0b95c1adead41702b12a59f35 (patch)
tree33b7931d23d322b8f809c568f5600f31f6009117 /lib/CodeGen/TwoAddressInstructionPass.cpp
parenta0d77375cb66caf9235a698526f2b2aae389f723 (diff)
downloadexternal_llvm-58d5ef24fd6c26a0b95c1adead41702b12a59f35.zip
external_llvm-58d5ef24fd6c26a0b95c1adead41702b12a59f35.tar.gz
external_llvm-58d5ef24fd6c26a0b95c1adead41702b12a59f35.tar.bz2
Teach 2addr pass to be do more commuting. If both uses of a two-address instruction are killed, but the first operand has a use before and after the def, commute if the second operand does not suffer from the same issue.
%reg1028<def> = EXTRACT_SUBREG %reg1027<kill>, 1 %reg1029<def> = MOV8rr %reg1028 %reg1029<def> = SHR8ri %reg1029, 7, %EFLAGS<imp-def,dead> insert => %reg1030<def> = MOV8rr %reg1028 %reg1030<def> = ADD8rr %reg1028<kill>, %reg1029<kill>, %EFLAGS<imp-def,dead> In this case, it might not be possible to coalesce the second MOV8rr instruction if the first one is coalesced. So it would be profitable to commute it: %reg1028<def> = EXTRACT_SUBREG %reg1027<kill>, 1 %reg1029<def> = MOV8rr %reg1028 %reg1029<def> = SHR8ri %reg1029, 7, %EFLAGS<imp-def,dead> insert => %reg1030<def> = MOV8rr %reg1029 %reg1030<def> = ADD8rr %reg1029<kill>, %reg1028<kill>, %EFLAGS<imp-def,dead> git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@62954 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/TwoAddressInstructionPass.cpp')
-rw-r--r--lib/CodeGen/TwoAddressInstructionPass.cpp110
1 files changed, 104 insertions, 6 deletions
diff --git a/lib/CodeGen/TwoAddressInstructionPass.cpp b/lib/CodeGen/TwoAddressInstructionPass.cpp
index 071b399..5cf2ffd 100644
--- a/lib/CodeGen/TwoAddressInstructionPass.cpp
+++ b/lib/CodeGen/TwoAddressInstructionPass.cpp
@@ -49,6 +49,7 @@ using namespace llvm;
STATISTIC(NumTwoAddressInstrs, "Number of two-address instructions");
STATISTIC(NumCommuted , "Number of instructions commuted to coalesce");
+STATISTIC(NumAggrCommuted , "Number of instructions aggressively commuted");
STATISTIC(NumConvertedTo3Addr, "Number of instructions promoted to 3-address");
STATISTIC(Num3AddrSunk, "Number of 3-address instructions sunk");
STATISTIC(NumReMats, "Number of instructions re-materialized");
@@ -70,6 +71,15 @@ namespace {
MachineBasicBlock *MBB, unsigned Loc,
DenseMap<MachineInstr*, unsigned> &DistanceMap);
+ bool NoUseAfterLastDef(unsigned Reg, MachineBasicBlock *MBB, unsigned Dist,
+ DenseMap<MachineInstr*, unsigned> &DistanceMap,
+ unsigned &LastDef);
+
+ bool isProfitableToCommute(unsigned regB, unsigned regC,
+ MachineInstr *MI, MachineBasicBlock *MBB,
+ unsigned Dist,
+ DenseMap<MachineInstr*, unsigned> &DistanceMap);
+
bool CommuteInstruction(MachineBasicBlock::iterator &mi,
MachineFunction::iterator &mbbi,
unsigned RegC, unsigned Dist,
@@ -230,8 +240,6 @@ TwoAddressInstructionPass::isProfitableToReMat(unsigned Reg,
for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(Reg),
UE = MRI->use_end(); UI != UE; ++UI) {
MachineOperand &UseMO = UI.getOperand();
- if (!UseMO.isUse())
- continue;
MachineInstr *UseMI = UseMO.getParent();
MachineBasicBlock *UseMBB = UseMI->getParent();
if (UseMBB == MBB) {
@@ -255,6 +263,82 @@ TwoAddressInstructionPass::isProfitableToReMat(unsigned Reg,
return MBB == DefMI->getParent();
}
+/// NoUseAfterLastDef - Return true if there are no intervening uses between the
+/// last instruction in the MBB that defines the specified register and the
+/// two-address instruction which is being processed. It also returns the last
+/// def location by reference
+bool TwoAddressInstructionPass::NoUseAfterLastDef(unsigned Reg,
+ MachineBasicBlock *MBB, unsigned Dist,
+ DenseMap<MachineInstr*, unsigned> &DistanceMap,
+ unsigned &LastDef) {
+ LastDef = 0;
+ unsigned LastUse = Dist;
+ for (MachineRegisterInfo::reg_iterator I = MRI->reg_begin(Reg),
+ E = MRI->reg_end(); I != E; ++I) {
+ MachineOperand &MO = I.getOperand();
+ MachineInstr *MI = MO.getParent();
+ if (MI->getParent() != MBB)
+ continue;
+ DenseMap<MachineInstr*, unsigned>::iterator DI = DistanceMap.find(MI);
+ if (DI == DistanceMap.end())
+ continue;
+ if (MO.isUse() && DI->second < LastUse)
+ LastUse = DI->second;
+ if (MO.isDef() && DI->second > LastDef)
+ LastDef = DI->second;
+ }
+
+ return !(LastUse > LastDef && LastUse < Dist);
+}
+
+/// isProfitableToReMat - Return true if it's potentially profitable to commute
+/// the two-address instruction that's being processed.
+bool
+TwoAddressInstructionPass::isProfitableToCommute(unsigned regB, unsigned regC,
+ MachineInstr *MI, MachineBasicBlock *MBB,
+ unsigned Dist, DenseMap<MachineInstr*, unsigned> &DistanceMap) {
+ // Determine if it's profitable to commute this two address instruction. In
+ // general, we want no uses between this instruction and the definition of
+ // the two-address register.
+ // e.g.
+ // %reg1028<def> = EXTRACT_SUBREG %reg1027<kill>, 1
+ // %reg1029<def> = MOV8rr %reg1028
+ // %reg1029<def> = SHR8ri %reg1029, 7, %EFLAGS<imp-def,dead>
+ // insert => %reg1030<def> = MOV8rr %reg1028
+ // %reg1030<def> = ADD8rr %reg1028<kill>, %reg1029<kill>, %EFLAGS<imp-def,dead>
+ // In this case, it might not be possible to coalesce the second MOV8rr
+ // instruction if the first one is coalesced. So it would be profitable to
+ // commute it:
+ // %reg1028<def> = EXTRACT_SUBREG %reg1027<kill>, 1
+ // %reg1029<def> = MOV8rr %reg1028
+ // %reg1029<def> = SHR8ri %reg1029, 7, %EFLAGS<imp-def,dead>
+ // insert => %reg1030<def> = MOV8rr %reg1029
+ // %reg1030<def> = ADD8rr %reg1029<kill>, %reg1028<kill>, %EFLAGS<imp-def,dead>
+
+ if (!MI->killsRegister(regC))
+ return false;
+
+ // Ok, we have something like:
+ // %reg1030<def> = ADD8rr %reg1028<kill>, %reg1029<kill>, %EFLAGS<imp-def,dead>
+ // let's see if it's worth commuting it.
+
+ // If there is a use of regC between its last def (could be livein) and this
+ // instruction, then bail.
+ unsigned LastDefC = 0;
+ if (!NoUseAfterLastDef(regC, MBB, Dist, DistanceMap, LastDefC))
+ return false;
+
+ // If there is a use of regB between its last def (could be livein) and this
+ // instruction, then go ahead and make this transformation.
+ unsigned LastDefB = 0;
+ if (!NoUseAfterLastDef(regB, MBB, Dist, DistanceMap, LastDefB))
+ return true;
+
+ // Since there are no intervening uses for both registers, then commute
+ // if the def of regC is closer. Its live interval is shorter.
+ return LastDefB && LastDefC && LastDefC > LastDefB;
+}
+
/// CommuteInstruction - Commute a two-address instruction and update the basic
/// block, distance map, and live variables if needed. Return true if it is
/// successful.
@@ -419,6 +503,17 @@ bool TwoAddressInstructionPass::runOnMachineFunction(MachineFunction &MF) {
}
}
+ // If it's profitable to commute the instruction, do so.
+ if (TID.isCommutable() && mi->getNumOperands() >= 3) {
+ unsigned regC = mi->getOperand(3-si).getReg();
+ if (isProfitableToCommute(regB, regC, mi, mbbi, Dist, DistanceMap))
+ if (CommuteInstruction(mi, mbbi, regC, Dist, DistanceMap)) {
+ ++NumAggrCommuted;
+ ++NumCommuted;
+ regB = regC;
+ }
+ }
+
InstructionRearranged:
const TargetRegisterClass* rc = MRI->getRegClass(regA);
MachineInstr *DefMI = MRI->getVRegDef(regB);
@@ -436,7 +531,10 @@ bool TwoAddressInstructionPass::runOnMachineFunction(MachineFunction &MF) {
TII->copyRegToReg(*mbbi, mi, regA, regB, rc, rc);
}
- MachineBasicBlock::iterator prevMi = prior(mi);
+ MachineBasicBlock::iterator prevMI = prior(mi);
+ // Update DistanceMap.
+ DistanceMap.insert(std::make_pair(prevMI, Dist));
+ DistanceMap[mi] = ++Dist;
// Update live variables for regB.
if (LV) {
@@ -446,13 +544,13 @@ bool TwoAddressInstructionPass::runOnMachineFunction(MachineFunction &MF) {
varInfoB.UsedBlocks[mbbi->getNumber()] = true;
if (LV->removeVirtualRegisterKilled(regB, mi))
- LV->addVirtualRegisterKilled(regB, prevMi);
+ LV->addVirtualRegisterKilled(regB, prevMI);
if (LV->removeVirtualRegisterDead(regB, mi))
- LV->addVirtualRegisterDead(regB, prevMi);
+ LV->addVirtualRegisterDead(regB, prevMI);
}
- DOUT << "\t\tprepend:\t"; DEBUG(prevMi->print(*cerr.stream(), &TM));
+ DOUT << "\t\tprepend:\t"; DEBUG(prevMI->print(*cerr.stream(), &TM));
// Replace all occurences of regB with regA.
for (unsigned i = 0, e = mi->getNumOperands(); i != e; ++i) {