[SystemZ] Use subregs for 64-bit truncating stores
[oota-llvm.git] / lib / Target / SystemZ / SystemZInstrInfo.cpp
index 54a8669359907e140b487c60534d00899c936974..d20487ad36797077aa0e9d6c2e2e83f114f0aaeb 100644 (file)
@@ -311,18 +311,11 @@ bool SystemZInstrInfo::analyzeCompare(const MachineInstr *MI,
   return false;
 }
 
-// If Reg is a virtual register that is used by only a single non-debug
-// instruction, return the defining instruction, otherwise return null.
-static MachineInstr *getDefSingleUse(const MachineRegisterInfo *MRI,
-                                     unsigned Reg) {
+// If Reg is a virtual register, return its definition, otherwise return null.
+static MachineInstr *getDef(unsigned Reg,
+                            const MachineRegisterInfo *MRI) {
   if (TargetRegisterInfo::isPhysicalRegister(Reg))
     return 0;
-
-  MachineRegisterInfo::use_nodbg_iterator I = MRI->use_nodbg_begin(Reg);
-  MachineRegisterInfo::use_nodbg_iterator E = MRI->use_nodbg_end();
-  if (I == E || llvm::next(I) != E)
-    return 0;
-
   return MRI->getUniqueVRegDef(Reg);
 }
 
@@ -333,42 +326,53 @@ static bool isShift(MachineInstr *MI, int Opcode, int64_t Imm) {
           MI->getOperand(3).getImm() == Imm);
 }
 
+// If the destination of MI has no uses, delete it as dead.
+static void eraseIfDead(MachineInstr *MI, const MachineRegisterInfo *MRI) {
+  if (MRI->use_nodbg_empty(MI->getOperand(0).getReg()))
+    MI->eraseFromParent();
+}
+
 // Compare compares SrcReg against zero.  Check whether SrcReg contains
-// the result of an IPM sequence that is only used by Compare.  Try to
-// delete both of them if so and return true if a change was made.
-static bool removeIPM(MachineInstr *Compare, unsigned SrcReg,
-                      const MachineRegisterInfo *MRI,
-                      const TargetRegisterInfo *TRI) {
-  MachineInstr *SRA = getDefSingleUse(MRI, SrcReg);
-  if (!SRA || !isShift(SRA, SystemZ::SRA, 30))
+// the result of an IPM sequence whose input CC survives until Compare,
+// and whether Compare is therefore redundant.  Delete it and return
+// true if so.
+static bool removeIPMBasedCompare(MachineInstr *Compare, unsigned SrcReg,
+                                  const MachineRegisterInfo *MRI,
+                                  const TargetRegisterInfo *TRI) {
+  MachineInstr *LGFR = 0;
+  MachineInstr *RLL = getDef(SrcReg, MRI);
+  if (RLL && RLL->getOpcode() == SystemZ::LGFR) {
+    LGFR = RLL;
+    RLL = getDef(LGFR->getOperand(1).getReg(), MRI);
+  }
+  if (!RLL || !isShift(RLL, SystemZ::RLL, 31))
     return false;
 
-  MachineInstr *SLL = getDefSingleUse(MRI, SRA->getOperand(1).getReg());
-  if (!SLL || !isShift(SLL, SystemZ::SLL, 2))
+  MachineInstr *SRL = getDef(RLL->getOperand(1).getReg(), MRI);
+  if (!SRL || !isShift(SRL, SystemZ::SRL, 28))
     return false;
 
-  MachineInstr *IPM = getDefSingleUse(MRI, SLL->getOperand(1).getReg());
+  MachineInstr *IPM = getDef(SRL->getOperand(1).getReg(), MRI);
   if (!IPM || IPM->getOpcode() != SystemZ::IPM)
     return false;
 
   // Check that there are no assignments to CC between the IPM and Compare,
-  // except for the SRA that we'd like to delete.  We can ignore SLL because
-  // it does not assign to CC.  We can also ignore uses of the SRA CC result,
-  // since it is effectively restoring CC to the value it had before IPM
-  // (for all current use cases).
   if (IPM->getParent() != Compare->getParent())
     return false;
   MachineBasicBlock::iterator MBBI = IPM, MBBE = Compare;
   for (++MBBI; MBBI != MBBE; ++MBBI) {
     MachineInstr *MI = MBBI;
-    if (MI != SRA && MI->modifiesRegister(SystemZ::CC, TRI))
+    if (MI->modifiesRegister(SystemZ::CC, TRI))
       return false;
   }
 
-  IPM->eraseFromParent();
-  SLL->eraseFromParent();
-  SRA->eraseFromParent();
   Compare->eraseFromParent();
+  if (LGFR)
+    eraseIfDead(LGFR, MRI);
+  eraseIfDead(RLL, MRI);
+  eraseIfDead(SRL, MRI);
+  eraseIfDead(IPM, MRI);
+
   return true;
 }
 
@@ -381,7 +385,7 @@ SystemZInstrInfo::optimizeCompareInstr(MachineInstr *Compare,
   bool IsLogical = (Compare->getDesc().TSFlags & SystemZII::IsLogical) != 0;
   if (Value == 0 &&
       !IsLogical &&
-      removeIPM(Compare, SrcReg, MRI, TM.getRegisterInfo()))
+      removeIPMBasedCompare(Compare, SrcReg, MRI, TM.getRegisterInfo()))
     return true;
   return false;
 }
@@ -790,11 +794,21 @@ SystemZInstrInfo::getBranchInfo(const MachineInstr *MI) const {
     return SystemZII::Branch(SystemZII::BranchC, SystemZ::CCMASK_ICMP,
                              MI->getOperand(2).getImm(), &MI->getOperand(3));
 
+  case SystemZ::CLIJ:
+  case SystemZ::CLRJ:
+    return SystemZII::Branch(SystemZII::BranchCL, SystemZ::CCMASK_ICMP,
+                             MI->getOperand(2).getImm(), &MI->getOperand(3));
+
   case SystemZ::CGIJ:
   case SystemZ::CGRJ:
     return SystemZII::Branch(SystemZII::BranchCG, SystemZ::CCMASK_ICMP,
                              MI->getOperand(2).getImm(), &MI->getOperand(3));
 
+  case SystemZ::CLGIJ:
+  case SystemZ::CLGRJ:
+    return SystemZII::Branch(SystemZII::BranchCLG, SystemZ::CCMASK_ICMP,
+                             MI->getOperand(2).getImm(), &MI->getOperand(3));
+
   default:
     llvm_unreachable("Unrecognized branch opcode");
   }
@@ -805,7 +819,7 @@ void SystemZInstrInfo::getLoadStoreOpcodes(const TargetRegisterClass *RC,
                                            unsigned &StoreOpcode) const {
   if (RC == &SystemZ::GR32BitRegClass || RC == &SystemZ::ADDR32BitRegClass) {
     LoadOpcode = SystemZ::L;
-    StoreOpcode = SystemZ::ST32;
+    StoreOpcode = SystemZ::ST;
   } else if (RC == &SystemZ::GR64BitRegClass ||
              RC == &SystemZ::ADDR64BitRegClass) {
     LoadOpcode = SystemZ::LG;
@@ -923,6 +937,14 @@ unsigned SystemZInstrInfo::getCompareAndBranch(unsigned Opcode,
     return MI && isInt<8>(MI->getOperand(1).getImm()) ? SystemZ::CIJ : 0;
   case SystemZ::CGHI:
     return MI && isInt<8>(MI->getOperand(1).getImm()) ? SystemZ::CGIJ : 0;
+  case SystemZ::CLR:
+    return SystemZ::CLRJ;
+  case SystemZ::CLGR:
+    return SystemZ::CLGRJ;
+  case SystemZ::CLFI:
+    return MI && isUInt<8>(MI->getOperand(1).getImm()) ? SystemZ::CLIJ : 0;
+  case SystemZ::CLGFI:
+    return MI && isUInt<8>(MI->getOperand(1).getImm()) ? SystemZ::CLGIJ : 0;
   default:
     return 0;
   }