[llvm-commits] CVS: llvm/lib/CodeGen/TwoAddressInstructionPass.cpp

Chris Lattner lattner at cs.uiuc.edu
Sat Jan 1 18:34:24 PST 2005



Changes in directory llvm/lib/CodeGen:

TwoAddressInstructionPass.cpp updated: 1.27 -> 1.28
---
Log message:

Make the 2-address instruction lowering pass smarter in two ways:

1. If we are two-addressing a commutable instruction and the LHS is not the
   last use of the variable, see if the instruction is the last use of the
   RHS.  If so, commute the instruction, allowing us to avoid a 
   register-register copy in many cases for common instructions like ADD, OR,
   AND, etc on X86.
2. If #1 doesn't hold, and if this is an instruction that also existing in
   3-address form, promote the instruction to a 3-address instruction to
   avoid the register-register copy.  We can do this for several common 
   instructions in X86, including ADDrr, INC, DEC, etc.

This patch implements test/Regression/CodeGen/X86/commute-two-addr.ll,
overlap-add.ll, and overlap-shift.ll when I check in the X86 support for it.


---
Diffs of the changes:  (+62 -18)

Index: llvm/lib/CodeGen/TwoAddressInstructionPass.cpp
diff -u llvm/lib/CodeGen/TwoAddressInstructionPass.cpp:1.27 llvm/lib/CodeGen/TwoAddressInstructionPass.cpp:1.28
--- llvm/lib/CodeGen/TwoAddressInstructionPass.cpp:1.27	Wed Sep  1 17:55:35 2004
+++ llvm/lib/CodeGen/TwoAddressInstructionPass.cpp	Sat Jan  1 20:34:12 2005
@@ -43,8 +43,12 @@
 using namespace llvm;
 
 namespace {
-  Statistic<> numTwoAddressInstrs("twoaddressinstruction",
+  Statistic<> NumTwoAddressInstrs("twoaddressinstruction",
                                   "Number of two-address instructions");
+  Statistic<> NumCommuted("twoaddressinstruction",
+                          "Number of instructions commuted to coallesce");
+  Statistic<> NumConvertedTo3Addr("twoaddressinstruction",
+                                "Number of instructions promoted to 3-address");
 
   struct TwoAddressInstructionPass : public MachineFunctionPass {
     virtual void getAnalysisUsage(AnalysisUsage &AU) const;
@@ -60,6 +64,7 @@
 const PassInfo *llvm::TwoAddressInstructionPassID = X.getPassInfo();
 
 void TwoAddressInstructionPass::getAnalysisUsage(AnalysisUsage &AU) const {
+  AU.addRequired<LiveVariables>();
   AU.addPreserved<LiveVariables>();
   AU.addPreservedID(PHIEliminationID);
   MachineFunctionPass::getAnalysisUsage(AU);
@@ -73,7 +78,7 @@
   const TargetMachine &TM = MF.getTarget();
   const MRegisterInfo &MRI = *TM.getRegisterInfo();
   const TargetInstrInfo &TII = *TM.getInstrInfo();
-  LiveVariables* LV = getAnalysisToUpdate<LiveVariables>();
+  LiveVariables &LV = getAnalysis<LiveVariables>();
 
   bool MadeChange = false;
 
@@ -91,7 +96,7 @@
       if (!TII.isTwoAddrInstr(opcode))
         continue;
 
-      ++numTwoAddressInstrs;
+      ++NumTwoAddressInstrs;
       DEBUG(std::cerr << '\t'; mi->print(std::cerr, &TM));
       assert(mi->getOperand(1).isRegister() && mi->getOperand(1).getReg() &&
              mi->getOperand(1).isUse() && "two address instruction invalid");
@@ -111,34 +116,73 @@
                MRegisterInfo::isVirtualRegister(regB) &&
                "cannot update physical register live information");
 
-        // first make sure we do not have a use of a in the
-        // instruction (a = b + a for example) because our
-        // transformation will not work. This should never occur
-        // because we are in SSA form.
 #ifndef NDEBUG
+        // First, verify that we do not have a use of a in the instruction (a =
+        // b + a for example) because our transformation will not work. This
+        // should never occur because we are in SSA form.
         for (unsigned i = 1; i != mi->getNumOperands(); ++i)
           assert(!mi->getOperand(i).isRegister() ||
                  mi->getOperand(i).getReg() != regA);
 #endif
 
+        // If this instruction is not the killing user of B, see if we can
+        // rearrange the code to make it so.  Making it the killing user will
+        // allow us to coallesce A and B together, eliminating the copy we are
+        // about to insert.
+        if (!LV.KillsRegister(mi, regB)) {
+          const TargetInstrDescriptor &TID = TII.get(opcode);
+
+          // If this instruction is commutative, check to see if C dies.  If so,
+          // swap the B and C operands.  This makes the live ranges of A and C
+          // joinable.
+          if (TID.Flags & M_COMMUTABLE) {
+            assert(mi->getOperand(2).isRegister() &&
+                   "Not a proper commutative instruction!");
+            unsigned regC = mi->getOperand(2).getReg();
+            if (LV.KillsRegister(mi, regC)) {
+              DEBUG(std::cerr << "2addr: COMMUTING  : " << *mi);
+              mi->SetMachineOperandReg(2, regB);
+              mi->SetMachineOperandReg(1, regC);
+              DEBUG(std::cerr << "2addr: COMMUTED TO: " << *mi);
+              ++NumCommuted;
+              regB = regC;
+              goto InstructionRearranged;
+            }
+          }
+          // If this instruction is potentially convertible to a true
+          // three-address instruction, 
+          if (TID.Flags & M_CONVERTIBLE_TO_3_ADDR)
+            if (MachineInstr *New = TII.convertToThreeAddress(mi)) {
+              DEBUG(std::cerr << "2addr: CONVERTING 2-ADDR: " << *mi);
+              DEBUG(std::cerr << "2addr:         TO 3-ADDR: " << *New);
+              LV.instructionChanged(mi, New);  // Update live variables
+              mbbi->insert(mi, New);           // Insert the new inst
+              mbbi->erase(mi);                 // Nuke the old inst.
+              mi = New;
+              ++NumConvertedTo3Addr;
+              assert(!TII.isTwoAddrInstr(New->getOpcode()) &&
+                     "convertToThreeAddress returned a 2-addr instruction??");
+              // Done with this instruction.
+              continue;
+            }
+        }
+      InstructionRearranged:
         const TargetRegisterClass* rc = MF.getSSARegMap()->getRegClass(regA);
         MRI.copyRegToReg(*mbbi, mi, regA, regB, rc);
 
         MachineBasicBlock::iterator prevMi = prior(mi);
         DEBUG(std::cerr << "\t\tprepend:\t"; prevMi->print(std::cerr, &TM));
 
-        if (LV) {
-          // update live variables for regA
-          LiveVariables::VarInfo& varInfo = LV->getVarInfo(regA);
-          varInfo.DefInst = prevMi;
-
-          // update live variables for regB
-          if (LV->removeVirtualRegisterKilled(regB, mbbi, mi))
-            LV->addVirtualRegisterKilled(regB, prevMi);
+        // Update live variables for regA
+        LiveVariables::VarInfo& varInfo = LV.getVarInfo(regA);
+        varInfo.DefInst = prevMi;
+
+        // update live variables for regB
+        if (LV.removeVirtualRegisterKilled(regB, mbbi, mi))
+          LV.addVirtualRegisterKilled(regB, prevMi);
 
-          if (LV->removeVirtualRegisterDead(regB, mbbi, mi))
-            LV->addVirtualRegisterDead(regB, prevMi);
-        }
+        if (LV.removeVirtualRegisterDead(regB, mbbi, mi))
+          LV.addVirtualRegisterDead(regB, prevMi);
 
         // replace all occurences of regB with regA
         for (unsigned i = 1, e = mi->getNumOperands(); i != e; ++i) {






More information about the llvm-commits mailing list