Rename getABITypeSize to getTypePaddedSize, as
[oota-llvm.git] / lib / CodeGen / LowerSubregs.cpp
index 8945dd57b1851df2bb7d446f831a96044abce415..9af276fad623fa689bd295a80b6396af330ddd80 100644 (file)
@@ -6,6 +6,13 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
+//
+// This file defines a MachineFunction pass which runs after register
+// allocation that turns subreg insert/extract instructions into register
+// copies, as needed. This ensures correct codegen even if the coalescer
+// isn't able to remove all subreg instructions.
+//
+//===----------------------------------------------------------------------===//
 
 #define DEBUG_TYPE "lowersubregs"
 #include "llvm/CodeGen/Passes.h"
@@ -24,17 +31,29 @@ namespace {
   struct VISIBILITY_HIDDEN LowerSubregsInstructionPass
    : public MachineFunctionPass {
     static char ID; // Pass identification, replacement for typeid
-    LowerSubregsInstructionPass() : MachineFunctionPass((intptr_t)&ID) {}
+    LowerSubregsInstructionPass() : MachineFunctionPass(&ID) {}
     
     const char *getPassName() const {
       return "Subregister lowering instruction pass";
     }
 
+    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+      AU.addPreservedID(MachineLoopInfoID);
+      AU.addPreservedID(MachineDominatorsID);
+      MachineFunctionPass::getAnalysisUsage(AU);
+    }
+
     /// runOnMachineFunction - pass entry point
     bool runOnMachineFunction(MachineFunction&);
     
     bool LowerExtract(MachineInstr *MI);
     bool LowerInsert(MachineInstr *MI);
+    bool LowerSubregToReg(MachineInstr *MI);
+
+    void TransferDeadFlag(MachineInstr *MI, unsigned DstReg,
+                          const TargetRegisterInfo &TRI);
+    void TransferKillFlag(MachineInstr *MI, unsigned SrcReg,
+                          const TargetRegisterInfo &TRI);
   };
 
   char LowerSubregsInstructionPass::ID = 0;
@@ -44,149 +63,186 @@ FunctionPass *llvm::createLowerSubregsPass() {
   return new LowerSubregsInstructionPass(); 
 }
 
-bool LowerSubregsInstructionPass::LowerExtract(MachineInstr *MI) {
-   MachineBasicBlock *MBB = MI->getParent();
-   MachineFunction &MF = *MBB->getParent();
-   const TargetRegisterInfo &TRI = *MF.getTarget().getRegisterInfo();
-   const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
-   
-   assert(MI->getOperand(0).isRegister() && MI->getOperand(0).isDef() &&
-          MI->getOperand(1).isRegister() && MI->getOperand(1).isUse() &&
-          MI->getOperand(2).isImmediate() && "Malformed extract_subreg");
-
-   unsigned SuperReg = MI->getOperand(1).getReg();
-   unsigned SubIdx = MI->getOperand(2).getImm();
-
-   assert(TargetRegisterInfo::isPhysicalRegister(SuperReg) &&
-          "Extract supperg source must be a physical register");
-   unsigned SrcReg = TRI.getSubReg(SuperReg, SubIdx);
-   unsigned DstReg = MI->getOperand(0).getReg();
-
-   DOUT << "subreg: CONVERTING: " << *MI;
-
-   if (SrcReg != DstReg) {
-     const TargetRegisterClass *TRC = 0;
-     if (TargetRegisterInfo::isPhysicalRegister(DstReg)) {
-       TRC = TRI.getPhysicalRegisterRegClass(DstReg);
-     } else {
-       TRC = MF.getRegInfo().getRegClass(DstReg);
-     }
-     assert(TRC == TRI.getPhysicalRegisterRegClass(SrcReg) &&
-             "Extract subreg and Dst must be of same register class");
-
-     TII.copyRegToReg(*MBB, MI, DstReg, SrcReg, TRC, TRC);
-     MachineBasicBlock::iterator dMI = MI;
-     DOUT << "subreg: " << *(--dMI);
-   }
-
-   DOUT << "\n";
-   MBB->remove(MI);
-   return true;
+/// TransferDeadFlag - MI is a pseudo-instruction with DstReg dead,
+/// and the lowered replacement instructions immediately precede it.
+/// Mark the replacement instructions with the dead flag.
+void
+LowerSubregsInstructionPass::TransferDeadFlag(MachineInstr *MI,
+                                              unsigned DstReg,
+                                              const TargetRegisterInfo &TRI) {
+  for (MachineBasicBlock::iterator MII =
+        prior(MachineBasicBlock::iterator(MI)); ; --MII) {
+    if (MII->addRegisterDead(DstReg, &TRI))
+      break;
+    assert(MII != MI->getParent()->begin() &&
+           "copyRegToReg output doesn't reference destination register!");
+  }
 }
 
+/// TransferKillFlag - MI is a pseudo-instruction with SrcReg killed,
+/// and the lowered replacement instructions immediately precede it.
+/// Mark the replacement instructions with the kill flag.
+void
+LowerSubregsInstructionPass::TransferKillFlag(MachineInstr *MI,
+                                              unsigned SrcReg,
+                                              const TargetRegisterInfo &TRI) {
+  for (MachineBasicBlock::iterator MII =
+        prior(MachineBasicBlock::iterator(MI)); ; --MII) {
+    if (MII->addRegisterKilled(SrcReg, &TRI))
+      break;
+    assert(MII != MI->getParent()->begin() &&
+           "copyRegToReg output doesn't reference source register!");
+  }
+}
 
-bool LowerSubregsInstructionPass::LowerInsert(MachineInstr *MI) {
+bool LowerSubregsInstructionPass::LowerExtract(MachineInstr *MI) {
+  MachineBasicBlock *MBB = MI->getParent();
+  MachineFunction &MF = *MBB->getParent();
+  const TargetRegisterInfo &TRI = *MF.getTarget().getRegisterInfo();
+  const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
+  
+  assert(MI->getOperand(0).isReg() && MI->getOperand(0).isDef() &&
+         MI->getOperand(1).isReg() && MI->getOperand(1).isUse() &&
+         MI->getOperand(2).isImm() && "Malformed extract_subreg");
+
+  unsigned DstReg   = MI->getOperand(0).getReg();
+  unsigned SuperReg = MI->getOperand(1).getReg();
+  unsigned SubIdx   = MI->getOperand(2).getImm();
+  unsigned SrcReg   = TRI.getSubReg(SuperReg, SubIdx);
+
+  assert(TargetRegisterInfo::isPhysicalRegister(SuperReg) &&
+         "Extract supperg source must be a physical register");
+  assert(TargetRegisterInfo::isPhysicalRegister(DstReg) &&
+         "Extract destination must be in a physical register");
+         
+  DOUT << "subreg: CONVERTING: " << *MI;
+
+  if (SrcReg == DstReg) {
+    // No need to insert an identify copy instruction.
+    DOUT << "subreg: eliminated!";
+    // Find the kill of the destination register's live range, and insert
+    // a kill of the source register at that point.
+    if (MI->getOperand(1).isKill() && !MI->getOperand(0).isDead())
+      for (MachineBasicBlock::iterator MII =
+             next(MachineBasicBlock::iterator(MI));
+           MII != MBB->end(); ++MII)
+        if (MII->killsRegister(DstReg, &TRI)) {
+          MII->addRegisterKilled(SuperReg, &TRI, /*AddIfNotFound=*/true);
+          break;
+        }
+  } else {
+    // Insert copy
+    const TargetRegisterClass *TRC = TRI.getPhysicalRegisterRegClass(DstReg);
+    assert(TRC == TRI.getPhysicalRegisterRegClass(SrcReg) &&
+            "Extract subreg and Dst must be of same register class");
+    TII.copyRegToReg(*MBB, MI, DstReg, SrcReg, TRC, TRC);
+    // Transfer the kill/dead flags, if needed.
+    if (MI->getOperand(0).isDead())
+      TransferDeadFlag(MI, DstReg, TRI);
+    if (MI->getOperand(1).isKill())
+      TransferKillFlag(MI, SrcReg, TRI);
+
+#ifndef NDEBUG
+    MachineBasicBlock::iterator dMI = MI;
+    DOUT << "subreg: " << *(--dMI);
+#endif
+  }
+
+  DOUT << "\n";
+  MBB->erase(MI);
+  return true;
+}
+
+bool LowerSubregsInstructionPass::LowerSubregToReg(MachineInstr *MI) {
   MachineBasicBlock *MBB = MI->getParent();
   MachineFunction &MF = *MBB->getParent();
   const TargetRegisterInfo &TRI = *MF.getTarget().getRegisterInfo(); 
   const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
-  assert((MI->getOperand(0).isRegister() && MI->getOperand(0).isDef()) &&
-         ((MI->getOperand(1).isRegister() && MI->getOperand(1).isUse()) || 
-            MI->getOperand(1).isImmediate()) &&
-         (MI->getOperand(2).isRegister() && MI->getOperand(2).isUse()) &&
-          MI->getOperand(3).isImmediate() && "Invalid insert_subreg");
+  assert((MI->getOperand(0).isReg() && MI->getOperand(0).isDef()) &&
+         MI->getOperand(1).isImm() &&
+         (MI->getOperand(2).isReg() && MI->getOperand(2).isUse()) &&
+          MI->getOperand(3).isImm() && "Invalid subreg_to_reg");
           
-  // Check if we're inserting into an implicit undef value.
-  bool isImplicit = MI->getOperand(1).isImmediate();
-  unsigned DstReg = MI->getOperand(0).getReg();
-  unsigned SrcReg = isImplicit ? DstReg : MI->getOperand(1).getReg();
-  unsigned InsReg = MI->getOperand(2).getReg();
-  unsigned SubIdx = MI->getOperand(3).getImm();     
+  unsigned DstReg  = MI->getOperand(0).getReg();
+  unsigned InsReg  = MI->getOperand(2).getReg();
+  unsigned SubIdx  = MI->getOperand(3).getImm();     
 
-  assert(SubIdx != 0 && "Invalid index for extract_subreg");
+  assert(SubIdx != 0 && "Invalid index for insert_subreg");
   unsigned DstSubReg = TRI.getSubReg(DstReg, SubIdx);
-
-  assert(TargetRegisterInfo::isPhysicalRegister(SrcReg) &&
-         "Insert superreg source must be in a physical register");
+  
   assert(TargetRegisterInfo::isPhysicalRegister(DstReg) &&
          "Insert destination must be in a physical register");
   assert(TargetRegisterInfo::isPhysicalRegister(InsReg) &&
          "Inserted value must be in a physical register");
 
   DOUT << "subreg: CONVERTING: " << *MI;
-       
-  // Check whether the implict subreg copy has side affects or not. Only copies
-  // into an undef value have no side affects, that is they can be eliminated
-  // without changing the semantics of the program.
-  bool copyHasSideAffects = isImplicit? 
-                  MI->getOperand(1).getImm() != TargetInstrInfo::IMPL_VAL_UNDEF
-                  : false; 
-       
-  // If the inserted register is already allocated into a subregister
-  // of the destination, we copy the subreg into the source
-  // However, this is only safe if the insert instruction is the kill
-  // of the source register
-  bool revCopyOrder = TRI.isSubRegister(DstReg, InsReg);
-  if (revCopyOrder && (InsReg != DstSubReg || copyHasSideAffects)) {
-    if (isImplicit || MI->getOperand(1).isKill()) {
-      DstSubReg = TRI.getSubReg(SrcReg, SubIdx);
-      // Insert sub-register copy
-      const TargetRegisterClass *TRC1 = 0;
-      if (TargetRegisterInfo::isPhysicalRegister(InsReg)) {
-        TRC1 = TRI.getPhysicalRegisterRegClass(InsReg);
-      } else {
-        TRC1 = MF.getRegInfo().getRegClass(InsReg);
-      }
-      TII.copyRegToReg(*MBB, MI, DstSubReg, InsReg, TRC1, TRC1);
-
-#ifndef NDEBUG
-      MachineBasicBlock::iterator dMI = MI;
-      DOUT << "subreg: " << *(--dMI);
-#endif
-    } else {
-      assert(0 && "Don't know how to convert this insert");
-    }
-  }
-#ifndef NDEBUG
-  if (InsReg == DstSubReg && !copyHasSideAffects) {
-     DOUT << "subreg: Eliminated subreg copy\n";
-  }
-#endif
-
-  if (SrcReg != DstReg) {
-    // Insert super-register copy
-    const TargetRegisterClass *TRC0 = 0;
-    if (TargetRegisterInfo::isPhysicalRegister(DstReg)) {
-      TRC0 = TRI.getPhysicalRegisterRegClass(DstReg);
-    } else {
-      TRC0 = MF.getRegInfo().getRegClass(DstReg);
-    }
-    assert(TRC0 == TRI.getPhysicalRegisterRegClass(SrcReg) &&
-            "Insert superreg and Dst must be of same register class");
 
-    TII.copyRegToReg(*MBB, MI, DstReg, SrcReg, TRC0, TRC0);
+  if (DstSubReg == InsReg) {
+    // No need to insert an identify copy instruction.
+    DOUT << "subreg: eliminated!";
+  } else {
+    // Insert sub-register copy
+    const TargetRegisterClass *TRC0= TRI.getPhysicalRegisterRegClass(DstSubReg);
+    const TargetRegisterClass *TRC1= TRI.getPhysicalRegisterRegClass(InsReg);
+    TII.copyRegToReg(*MBB, MI, DstSubReg, InsReg, TRC0, TRC1);
+    // Transfer the kill/dead flags, if needed.
+    if (MI->getOperand(0).isDead())
+      TransferDeadFlag(MI, DstSubReg, TRI);
+    if (MI->getOperand(2).isKill())
+      TransferKillFlag(MI, InsReg, TRI);
 
 #ifndef NDEBUG
     MachineBasicBlock::iterator dMI = MI;
     DOUT << "subreg: " << *(--dMI);
 #endif
   }
-  
+
+  DOUT << "\n";
+  MBB->erase(MI);
+  return true;                    
+}
+
+bool LowerSubregsInstructionPass::LowerInsert(MachineInstr *MI) {
+  MachineBasicBlock *MBB = MI->getParent();
+  MachineFunction &MF = *MBB->getParent();
+  const TargetRegisterInfo &TRI = *MF.getTarget().getRegisterInfo(); 
+  const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
+  assert((MI->getOperand(0).isReg() && MI->getOperand(0).isDef()) &&
+         (MI->getOperand(1).isReg() && MI->getOperand(1).isUse()) &&
+         (MI->getOperand(2).isReg() && MI->getOperand(2).isUse()) &&
+          MI->getOperand(3).isImm() && "Invalid insert_subreg");
+          
+  unsigned DstReg = MI->getOperand(0).getReg();
 #ifndef NDEBUG
-  if (SrcReg == DstReg) {
-     DOUT << "subreg: Eliminated superreg copy\n";
-  }
+  unsigned SrcReg = MI->getOperand(1).getReg();
 #endif
+  unsigned InsReg = MI->getOperand(2).getReg();
+  unsigned SubIdx = MI->getOperand(3).getImm();     
 
-  if (!revCopyOrder && (InsReg != DstSubReg || copyHasSideAffects)) {
+  assert(DstReg == SrcReg && "insert_subreg not a two-address instruction?");
+  assert(SubIdx != 0 && "Invalid index for insert_subreg");
+  unsigned DstSubReg = TRI.getSubReg(DstReg, SubIdx);
+  
+  assert(TargetRegisterInfo::isPhysicalRegister(SrcReg) &&
+         "Insert superreg source must be in a physical register");
+  assert(TargetRegisterInfo::isPhysicalRegister(InsReg) &&
+         "Inserted value must be in a physical register");
+
+  DOUT << "subreg: CONVERTING: " << *MI;
+
+  if (DstSubReg == InsReg) {
+    // No need to insert an identify copy instruction.
+    DOUT << "subreg: eliminated!";
+  } else {
     // Insert sub-register copy
-    const TargetRegisterClass *TRC1 = 0;
-    if (TargetRegisterInfo::isPhysicalRegister(InsReg)) {
-      TRC1 = TRI.getPhysicalRegisterRegClass(InsReg);
-    } else {
-      TRC1 = MF.getRegInfo().getRegClass(InsReg);
-    }
-    TII.copyRegToReg(*MBB, MI, DstSubReg, InsReg, TRC1, TRC1);
+    const TargetRegisterClass *TRC0= TRI.getPhysicalRegisterRegClass(DstSubReg);
+    const TargetRegisterClass *TRC1= TRI.getPhysicalRegisterRegClass(InsReg);
+    TII.copyRegToReg(*MBB, MI, DstSubReg, InsReg, TRC0, TRC1);
+    // Transfer the kill/dead flags, if needed.
+    if (MI->getOperand(0).isDead())
+      TransferDeadFlag(MI, DstSubReg, TRI);
+    if (MI->getOperand(1).isKill())
+      TransferKillFlag(MI, InsReg, TRI);
 
 #ifndef NDEBUG
     MachineBasicBlock::iterator dMI = MI;
@@ -195,7 +251,7 @@ bool LowerSubregsInstructionPass::LowerInsert(MachineInstr *MI) {
   }
 
   DOUT << "\n";
-  MBB->remove(MI);
+  MBB->erase(MI);
   return true;                    
 }
 
@@ -220,6 +276,8 @@ bool LowerSubregsInstructionPass::runOnMachineFunction(MachineFunction &MF) {
         MadeChange |= LowerExtract(MI);
       } else if (MI->getOpcode() == TargetInstrInfo::INSERT_SUBREG) {
         MadeChange |= LowerInsert(MI);
+      } else if (MI->getOpcode() == TargetInstrInfo::SUBREG_TO_REG) {
+        MadeChange |= LowerSubregToReg(MI);
       }
     }
   }