[llvm-commits] [llvm] r48333 - in /llvm/trunk: lib/CodeGen/TwoAddressInstructionPass.cpp test/CodeGen/X86/2006-05-02-InstrSched2.ll test/CodeGen/X86/twoaddr-pass-sink.ll

Evan Cheng evan.cheng at apple.com
Wed Mar 12 23:37:55 PDT 2008


Author: evancheng
Date: Thu Mar 13 01:37:55 2008
New Revision: 48333

URL: http://llvm.org/viewvc/llvm-project?rev=48333&view=rev
Log:
TwoAddressInstructionPass enhancement. After it converts a two address instruction into a 3-address one, sink it past the instruction that kills the read-mod-write register if its definition is used past the kill. This reduces the number of live register by one.

Added:
    llvm/trunk/test/CodeGen/X86/twoaddr-pass-sink.ll
Modified:
    llvm/trunk/lib/CodeGen/TwoAddressInstructionPass.cpp
    llvm/trunk/test/CodeGen/X86/2006-05-02-InstrSched2.ll

Modified: llvm/trunk/lib/CodeGen/TwoAddressInstructionPass.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/TwoAddressInstructionPass.cpp?rev=48333&r1=48332&r2=48333&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/TwoAddressInstructionPass.cpp (original)
+++ llvm/trunk/lib/CodeGen/TwoAddressInstructionPass.cpp Thu Mar 13 01:37:55 2008
@@ -37,8 +37,9 @@
 #include "llvm/Target/TargetRegisterInfo.h"
 #include "llvm/Target/TargetInstrInfo.h"
 #include "llvm/Target/TargetMachine.h"
-#include "llvm/Support/Debug.h"
+#include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Compiler.h"
+#include "llvm/Support/Debug.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/STLExtras.h"
 using namespace llvm;
@@ -46,10 +47,22 @@
 STATISTIC(NumTwoAddressInstrs, "Number of two-address instructions");
 STATISTIC(NumCommuted        , "Number of instructions commuted to coalesce");
 STATISTIC(NumConvertedTo3Addr, "Number of instructions promoted to 3-address");
+STATISTIC(Num3AddrSunk,        "Number of 3-address instructions sunk");
+
+namespace {
+  static cl::opt<int>
+  SinkLimit("two-addr-sink-limit", cl::init(-1), cl::Hidden);
+}
 
 namespace {
   struct VISIBILITY_HIDDEN TwoAddressInstructionPass
    : public MachineFunctionPass {
+    const TargetInstrInfo *TII;
+    const TargetRegisterInfo *TRI;
+    MachineRegisterInfo *MRI;
+    LiveVariables *LV;
+
+  public:
     static char ID; // Pass identification, replacement for typeid
     TwoAddressInstructionPass() : MachineFunctionPass((intptr_t)&ID) {}
 
@@ -57,6 +70,11 @@
 
     /// runOnMachineFunction - pass entry point
     bool runOnMachineFunction(MachineFunction&);
+
+  private:
+    bool Sink3AddrInstruction(MachineBasicBlock *MBB, MachineInstr *MI,
+                              unsigned Reg,
+                              MachineBasicBlock::iterator OldPos);
   };
 
   char TwoAddressInstructionPass::ID = 0;
@@ -75,14 +93,113 @@
   MachineFunctionPass::getAnalysisUsage(AU);
 }
 
+/// Sink3AddrInstruction - A two-address instruction has been converted to a
+/// three-address instruction to avoid clobbering a register. Try to sink it
+/// past the instruction that would kill the above mentioned register to
+/// reduce register pressure.
+bool TwoAddressInstructionPass::Sink3AddrInstruction(MachineBasicBlock *MBB,
+                                           MachineInstr *MI, unsigned SavedReg,
+                                           MachineBasicBlock::iterator OldPos) {
+  // Check if it's safe to move this instruction.
+  bool SeenStore = true; // Be conservative.
+  if (!MI->isSafeToMove(TII, SeenStore))
+    return false;
+
+  unsigned DefReg = 0;
+  SmallSet<unsigned, 4> UseRegs;
+  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
+    const MachineOperand &MO = MI->getOperand(i);
+    if (!MO.isRegister())
+      continue;
+    unsigned MOReg = MO.getReg();
+    if (!MOReg)
+      continue;
+    if (MO.isUse() && MOReg != SavedReg)
+      UseRegs.insert(MO.getReg());
+    if (!MO.isDef())
+      continue;
+    if (MO.isImplicit())
+      // Don't try to move it if it implicitly defines a register.
+      return false;
+    if (DefReg)
+      // For now, don't move any instructions that define multiple registers.
+      return false;
+    DefReg = MO.getReg();
+  }
+
+  // Find the instruction that kills SavedReg.
+  MachineInstr *KillMI = NULL;
+  for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(SavedReg),
+         UE = MRI->use_end(); UI != UE; ++UI) {
+    MachineOperand &UseMO = UI.getOperand();
+    if (!UseMO.isKill())
+      continue;
+    KillMI = UseMO.getParent();
+    break;
+  }
+  if (!KillMI || KillMI->getParent() != MBB)
+    return false;
+
+  // If any of the definitions are used  by another instruction between
+  // the position and the kill use, then it's not safe to sink it.
+  // FIXME: This can be sped up if there is an easy way to query whether
+  // an instruction if before or after another instruction. Then we can
+  // use MachineRegisterInfo def / use instead.
+  MachineOperand *KillMO = NULL;
+  MachineBasicBlock::iterator KillPos = KillMI;
+  ++KillPos;
+  for (MachineBasicBlock::iterator I = next(OldPos); I != KillPos; ++I) {
+    MachineInstr *OtherMI = I;
+    for (unsigned i = 0, e = OtherMI->getNumOperands(); i != e; ++i) {
+      MachineOperand &MO = OtherMI->getOperand(i);
+      if (!MO.isRegister())
+        continue;
+      unsigned MOReg = MO.getReg();
+      if (!MOReg)
+        continue;
+      if (DefReg == MOReg)
+        return false;
+      if (MO.isKill()) {
+        if (OtherMI == KillMI && MOReg == SavedReg)
+          // Save the operand that kills the register. We want unset the kill
+          // marker is we can sink MI past it.
+          KillMO = &MO;
+        else if (UseRegs.count(MOReg))
+          // One of the uses is killed before the destination.
+          return false;
+      }
+    }
+  }
+
+  if (SinkLimit != -1 && Num3AddrSunk == (unsigned)SinkLimit)
+    return false;
+
+  // Update kill and LV information.
+  KillMO->setIsKill(false);
+  KillMO = MI->findRegisterUseOperand(SavedReg, false, TRI);
+  KillMO->setIsKill(true);
+  LiveVariables::VarInfo& VarInfo = LV->getVarInfo(SavedReg);
+  VarInfo.removeKill(KillMI);
+  VarInfo.Kills.push_back(MI);
+
+  // Move instruction to its destination.
+  MBB->remove(MI);
+  MBB->insert(KillPos, MI);
+
+  ++Num3AddrSunk;
+  return true;
+}
+
 /// runOnMachineFunction - Reduce two-address instructions to two
 /// operands.
 ///
 bool TwoAddressInstructionPass::runOnMachineFunction(MachineFunction &MF) {
   DOUT << "Machine Function\n";
   const TargetMachine &TM = MF.getTarget();
-  const TargetInstrInfo &TII = *TM.getInstrInfo();
-  LiveVariables &LV = getAnalysis<LiveVariables>();
+  MRI = &MF.getRegInfo();
+  TII = TM.getInstrInfo();
+  TRI = TM.getRegisterInfo();
+  LV = &getAnalysis<LiveVariables>();
 
   bool MadeChange = false;
 
@@ -150,14 +267,14 @@
               unsigned regC = mi->getOperand(3-si).getReg();
               if (mi->killsRegister(regC)) {
                 DOUT << "2addr: COMMUTING  : " << *mi;
-                MachineInstr *NewMI = TII.commuteInstruction(mi);
+                MachineInstr *NewMI = TII->commuteInstruction(mi);
                 if (NewMI == 0) {
                   DOUT << "2addr: COMMUTING FAILED!\n";
                 } else {
                   DOUT << "2addr: COMMUTED TO: " << *NewMI;
                   // If the instruction changed to commute it, update livevar.
                   if (NewMI != mi) {
-                    LV.instructionChanged(mi, NewMI);  // Update live variables
+                    LV->instructionChanged(mi, NewMI); // Update live variables
                     mbbi->insert(mi, NewMI);           // Insert the new inst
                     mbbi->erase(mi);                   // Nuke the old inst.
                     mi = NewMI;
@@ -180,11 +297,12 @@
                 assert(TID.getOperandConstraint(i, TOI::TIED_TO) == -1);
 #endif
 
-              if (MachineInstr *New = TII.convertToThreeAddress(mbbi, mi, LV)) {
+              if (MachineInstr *New=TII->convertToThreeAddress(mbbi, mi, *LV)) {
                 DOUT << "2addr: CONVERTING 2-ADDR: " << *mi;
                 DOUT << "2addr:         TO 3-ADDR: " << *New;
+                bool Sunk = Sink3AddrInstruction(mbbi, New, regB, mi);
                 mbbi->erase(mi);                 // Nuke the old inst.
-                mi = New;
+                if (!Sunk) mi = New;
                 ++NumConvertedTo3Addr;
                 // Done with this instruction.
                 break;
@@ -194,20 +312,20 @@
 
         InstructionRearranged:
           const TargetRegisterClass* rc = MF.getRegInfo().getRegClass(regA);
-          TII.copyRegToReg(*mbbi, mi, regA, regB, rc, rc);
+          TII->copyRegToReg(*mbbi, mi, regA, regB, rc, rc);
 
           MachineBasicBlock::iterator prevMi = prior(mi);
           DOUT << "\t\tprepend:\t"; DEBUG(prevMi->print(*cerr.stream(), &TM));
 
           // update live variables for regB
-          LiveVariables::VarInfo& varInfoB = LV.getVarInfo(regB);
+          LiveVariables::VarInfo& varInfoB = LV->getVarInfo(regB);
           // regB is used in this BB.
           varInfoB.UsedBlocks[mbbi->getNumber()] = true;
-          if (LV.removeVirtualRegisterKilled(regB, mbbi, mi))
-            LV.addVirtualRegisterKilled(regB, prevMi);
+          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 = 0, e = mi->getNumOperands(); i != e; ++i) {

Modified: llvm/trunk/test/CodeGen/X86/2006-05-02-InstrSched2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2006-05-02-InstrSched2.ll?rev=48333&r1=48332&r2=48333&view=diff

==============================================================================
--- llvm/trunk/test/CodeGen/X86/2006-05-02-InstrSched2.ll (original)
+++ llvm/trunk/test/CodeGen/X86/2006-05-02-InstrSched2.ll Thu Mar 13 01:37:55 2008
@@ -1,5 +1,5 @@
 ; RUN: llvm-upgrade < %s | llvm-as | llc -march=x86 -stats |& \
-; RUN:   grep asm-printer | grep 14
+; RUN:   grep asm-printer | grep 13
 
 void %_ZN9__gnu_cxx9hashtableISt4pairIKPKciES3_NS_4hashIS3_EESt10_Select1stIS5_E5eqstrSaIiEE14find_or_insertERKS5__cond_true456.i(sbyte* %tmp435.i, uint* %tmp449.i.out) {
 newFuncRoot:

Added: llvm/trunk/test/CodeGen/X86/twoaddr-pass-sink.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/twoaddr-pass-sink.ll?rev=48333&view=auto

==============================================================================
--- llvm/trunk/test/CodeGen/X86/twoaddr-pass-sink.ll (added)
+++ llvm/trunk/test/CodeGen/X86/twoaddr-pass-sink.ll Thu Mar 13 01:37:55 2008
@@ -0,0 +1,29 @@
+; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse2 -stats |& grep {Number of 3-address instructions sunk}
+
+define void @t2(<2 x i64>* %vDct, <2 x i64>* %vYp, i8* %skiplist, <2 x i64> %a1) nounwind  {
+entry:
+	%tmp25 = bitcast <2 x i64> %a1 to <8 x i16>		; <<8 x i16>> [#uses=1]
+	br label %bb
+bb:		; preds = %bb, %entry
+	%skiplist_addr.0.rec = phi i32 [ 0, %entry ], [ %indvar.next, %bb ]		; <i32> [#uses=3]
+	%vYp_addr.0.rec = shl i32 %skiplist_addr.0.rec, 3		; <i32> [#uses=3]
+	%vDct_addr.0 = getelementptr <2 x i64>* %vDct, i32 %vYp_addr.0.rec		; <<2 x i64>*> [#uses=1]
+	%vYp_addr.0 = getelementptr <2 x i64>* %vYp, i32 %vYp_addr.0.rec		; <<2 x i64>*> [#uses=1]
+	%skiplist_addr.0 = getelementptr i8* %skiplist, i32 %skiplist_addr.0.rec		; <i8*> [#uses=1]
+	%vDct_addr.0.sum43 = or i32 %vYp_addr.0.rec, 1		; <i32> [#uses=1]
+	%tmp7 = getelementptr <2 x i64>* %vDct, i32 %vDct_addr.0.sum43		; <<2 x i64>*> [#uses=1]
+	%tmp8 = load <2 x i64>* %tmp7, align 16		; <<2 x i64>> [#uses=1]
+	%tmp11 = load <2 x i64>* %vDct_addr.0, align 16		; <<2 x i64>> [#uses=1]
+	%tmp13 = bitcast <2 x i64> %tmp8 to <8 x i16>		; <<8 x i16>> [#uses=1]
+	%tmp15 = bitcast <2 x i64> %tmp11 to <8 x i16>		; <<8 x i16>> [#uses=1]
+	%tmp16 = shufflevector <8 x i16> %tmp15, <8 x i16> %tmp13, <8 x i32> < i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11 >		; <<8 x i16>> [#uses=1]
+	%tmp26 = mul <8 x i16> %tmp25, %tmp16		; <<8 x i16>> [#uses=1]
+	%tmp27 = bitcast <8 x i16> %tmp26 to <2 x i64>		; <<2 x i64>> [#uses=1]
+	store <2 x i64> %tmp27, <2 x i64>* %vYp_addr.0, align 16
+	%tmp37 = load i8* %skiplist_addr.0, align 1		; <i8> [#uses=1]
+	%tmp38 = icmp eq i8 %tmp37, 0		; <i1> [#uses=1]
+	%indvar.next = add i32 %skiplist_addr.0.rec, 1		; <i32> [#uses=1]
+	br i1 %tmp38, label %return, label %bb
+return:		; preds = %bb
+	ret void
+}





More information about the llvm-commits mailing list