- Avoid the longer SIB encoding on x86_64 when it's not needed.
[oota-llvm.git] / lib / Target / X86 / X86InstrInfo.cpp
index e123ae7e24acc2920adb98657fe39b0878b72016..0a3103af09affcf61ef6a59cbe11ac12e177a423 100644 (file)
@@ -667,6 +667,7 @@ bool X86InstrInfo::isMoveInstr(const MachineInstr& MI,
   default:
     return false;
   case X86::MOV8rr:
+  case X86::MOV8rr_NOREX:
   case X86::MOV16rr:
   case X86::MOV32rr: 
   case X86::MOV64rr:
@@ -1367,19 +1368,19 @@ X86InstrInfo::commuteInstruction(MachineInstr *MI, bool NewMI) const {
     case X86::CMOVG64rr:  Opc = X86::CMOVLE64rr; break;
     case X86::CMOVS16rr:  Opc = X86::CMOVNS16rr; break;
     case X86::CMOVS32rr:  Opc = X86::CMOVNS32rr; break;
-    case X86::CMOVS64rr:  Opc = X86::CMOVNS32rr; break;
+    case X86::CMOVS64rr:  Opc = X86::CMOVNS64rr; break;
     case X86::CMOVNS16rr: Opc = X86::CMOVS16rr; break;
     case X86::CMOVNS32rr: Opc = X86::CMOVS32rr; break;
     case X86::CMOVNS64rr: Opc = X86::CMOVS64rr; break;
     case X86::CMOVP16rr:  Opc = X86::CMOVNP16rr; break;
     case X86::CMOVP32rr:  Opc = X86::CMOVNP32rr; break;
-    case X86::CMOVP64rr:  Opc = X86::CMOVNP32rr; break;
+    case X86::CMOVP64rr:  Opc = X86::CMOVNP64rr; break;
     case X86::CMOVNP16rr: Opc = X86::CMOVP16rr; break;
     case X86::CMOVNP32rr: Opc = X86::CMOVP32rr; break;
     case X86::CMOVNP64rr: Opc = X86::CMOVP64rr; break;
     case X86::CMOVO16rr:  Opc = X86::CMOVNO16rr; break;
     case X86::CMOVO32rr:  Opc = X86::CMOVNO32rr; break;
-    case X86::CMOVO64rr:  Opc = X86::CMOVNO32rr; break;
+    case X86::CMOVO64rr:  Opc = X86::CMOVNO64rr; break;
     case X86::CMOVNO16rr: Opc = X86::CMOVO16rr; break;
     case X86::CMOVNO32rr: Opc = X86::CMOVO32rr; break;
     case X86::CMOVNO64rr: Opc = X86::CMOVO64rr; break;
@@ -1644,7 +1645,7 @@ X86InstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
 
 /// isHReg - Test if the given register is a physical h register.
 static bool isHReg(unsigned Reg) {
-  return Reg == X86::AH || Reg == X86::BH || Reg == X86::CH || Reg == X86::DH;
+  return X86::GR8_ABCD_HRegClass.contains(Reg);
 }
 
 bool X86InstrInfo::copyRegToReg(MachineBasicBlock &MBB,
@@ -1655,50 +1656,65 @@ bool X86InstrInfo::copyRegToReg(MachineBasicBlock &MBB,
   DebugLoc DL = DebugLoc::getUnknownLoc();
   if (MI != MBB.end()) DL = MI->getDebugLoc();
 
-  if (DestRC == SrcRC) {
+  // Determine if DstRC and SrcRC have a common superclass in common.
+  const TargetRegisterClass *CommonRC = DestRC;
+  if (DestRC == SrcRC)
+    /* Source and destination have the same register class. */;
+  else if (CommonRC->hasSuperClass(SrcRC))
+    CommonRC = SrcRC;
+  else if (!DestRC->hasSubClass(SrcRC))
+    CommonRC = 0;
+
+  if (CommonRC) {
     unsigned Opc;
-    if (DestRC == &X86::GR64RegClass) {
+    if (CommonRC == &X86::GR64RegClass) {
       Opc = X86::MOV64rr;
-    } else if (DestRC == &X86::GR32RegClass) {
+    } else if (CommonRC == &X86::GR32RegClass) {
       Opc = X86::MOV32rr;
-    } else if (DestRC == &X86::GR16RegClass) {
+    } else if (CommonRC == &X86::GR16RegClass) {
       Opc = X86::MOV16rr;
-    } else if (DestRC == &X86::GR8RegClass) {
-      // Copying two or from a physical H register requires a NOREX move.
-      // Otherwise use a normal move.
-      if (isHReg(DestReg) || isHReg(SrcReg))
+    } else if (CommonRC == &X86::GR8RegClass) {
+      // Copying to or from a physical H register on x86-64 requires a NOREX
+      // move.  Otherwise use a normal move.
+      if ((isHReg(DestReg) || isHReg(SrcReg)) &&
+          TM.getSubtarget<X86Subtarget>().is64Bit())
         Opc = X86::MOV8rr_NOREX;
       else
         Opc = X86::MOV8rr;
-    } else if (DestRC == &X86::GR64_RegClass) {
+    } else if (CommonRC == &X86::GR64_ABCDRegClass) {
       Opc = X86::MOV64rr;
-    } else if (DestRC == &X86::GR32_RegClass) {
+    } else if (CommonRC == &X86::GR32_ABCDRegClass) {
       Opc = X86::MOV32rr;
-    } else if (DestRC == &X86::GR16_RegClass) {
+    } else if (CommonRC == &X86::GR16_ABCDRegClass) {
       Opc = X86::MOV16rr;
-    } else if (DestRC == &X86::GR8_RegClass) {
+    } else if (CommonRC == &X86::GR8_ABCD_LRegClass) {
       Opc = X86::MOV8rr;
-    } else if (DestRC == &X86::GR64_NOREXRegClass) {
+    } else if (CommonRC == &X86::GR8_ABCD_HRegClass) {
+      if (TM.getSubtarget<X86Subtarget>().is64Bit())
+        Opc = X86::MOV8rr_NOREX;
+      else
+        Opc = X86::MOV8rr;
+    } else if (CommonRC == &X86::GR64_NOREXRegClass) {
       Opc = X86::MOV64rr;
-    } else if (DestRC == &X86::GR32_NOREXRegClass) {
+    } else if (CommonRC == &X86::GR32_NOREXRegClass) {
       Opc = X86::MOV32rr;
-    } else if (DestRC == &X86::GR16_NOREXRegClass) {
+    } else if (CommonRC == &X86::GR16_NOREXRegClass) {
       Opc = X86::MOV16rr;
-    } else if (DestRC == &X86::GR8_NOREXRegClass) {
+    } else if (CommonRC == &X86::GR8_NOREXRegClass) {
       Opc = X86::MOV8rr;
-    } else if (DestRC == &X86::RFP32RegClass) {
+    } else if (CommonRC == &X86::RFP32RegClass) {
       Opc = X86::MOV_Fp3232;
-    } else if (DestRC == &X86::RFP64RegClass || DestRC == &X86::RSTRegClass) {
+    } else if (CommonRC == &X86::RFP64RegClass || CommonRC == &X86::RSTRegClass) {
       Opc = X86::MOV_Fp6464;
-    } else if (DestRC == &X86::RFP80RegClass) {
+    } else if (CommonRC == &X86::RFP80RegClass) {
       Opc = X86::MOV_Fp8080;
-    } else if (DestRC == &X86::FR32RegClass) {
+    } else if (CommonRC == &X86::FR32RegClass) {
       Opc = X86::FsMOVAPSrr;
-    } else if (DestRC == &X86::FR64RegClass) {
+    } else if (CommonRC == &X86::FR64RegClass) {
       Opc = X86::FsMOVAPDrr;
-    } else if (DestRC == &X86::VR128RegClass) {
+    } else if (CommonRC == &X86::VR128RegClass) {
       Opc = X86::MOVAPSrr;
-    } else if (DestRC == &X86::VR64RegClass) {
+    } else if (CommonRC == &X86::VR64RegClass) {
       Opc = X86::MMX_MOVQ64rr;
     } else {
       return false;
@@ -1780,8 +1796,10 @@ bool X86InstrInfo::copyRegToReg(MachineBasicBlock &MBB,
   return false;
 }
 
-static unsigned getStoreRegOpcode(const TargetRegisterClass *RC,
-                                  bool isStackAligned) {
+static unsigned getStoreRegOpcode(unsigned SrcReg,
+                                  const TargetRegisterClass *RC,
+                                  bool isStackAligned,
+                                  TargetMachine &TM) {
   unsigned Opc = 0;
   if (RC == &X86::GR64RegClass) {
     Opc = X86::MOV64mr;
@@ -1790,15 +1808,26 @@ static unsigned getStoreRegOpcode(const TargetRegisterClass *RC,
   } else if (RC == &X86::GR16RegClass) {
     Opc = X86::MOV16mr;
   } else if (RC == &X86::GR8RegClass) {
-    Opc = X86::MOV8mr;
-  } else if (RC == &X86::GR64_RegClass) {
+    // Copying to or from a physical H register on x86-64 requires a NOREX
+    // move.  Otherwise use a normal move.
+    if (isHReg(SrcReg) &&
+        TM.getSubtarget<X86Subtarget>().is64Bit())
+      Opc = X86::MOV8mr_NOREX;
+    else
+      Opc = X86::MOV8mr;
+  } else if (RC == &X86::GR64_ABCDRegClass) {
     Opc = X86::MOV64mr;
-  } else if (RC == &X86::GR32_RegClass) {
+  } else if (RC == &X86::GR32_ABCDRegClass) {
     Opc = X86::MOV32mr;
-  } else if (RC == &X86::GR16_RegClass) {
+  } else if (RC == &X86::GR16_ABCDRegClass) {
     Opc = X86::MOV16mr;
-  } else if (RC == &X86::GR8_RegClass) {
+  } else if (RC == &X86::GR8_ABCD_LRegClass) {
     Opc = X86::MOV8mr;
+  } else if (RC == &X86::GR8_ABCD_HRegClass) {
+    if (TM.getSubtarget<X86Subtarget>().is64Bit())
+      Opc = X86::MOV8mr_NOREX;
+    else
+      Opc = X86::MOV8mr;
   } else if (RC == &X86::GR64_NOREXRegClass) {
     Opc = X86::MOV64mr;
   } else if (RC == &X86::GR32_NOREXRegClass) {
@@ -1837,7 +1866,7 @@ void X86InstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
   const MachineFunction &MF = *MBB.getParent();
   bool isAligned = (RI.getStackAlignment() >= 16) ||
     RI.needsStackRealignment(MF);
-  unsigned Opc = getStoreRegOpcode(RC, isAligned);
+  unsigned Opc = getStoreRegOpcode(SrcReg, RC, isAligned, TM);
   DebugLoc DL = DebugLoc::getUnknownLoc();
   if (MI != MBB.end()) DL = MI->getDebugLoc();
   addFrameReference(BuildMI(MBB, MI, DL, get(Opc)), FrameIdx)
@@ -1851,7 +1880,7 @@ void X86InstrInfo::storeRegToAddr(MachineFunction &MF, unsigned SrcReg,
                                   SmallVectorImpl<MachineInstr*> &NewMIs) const {
   bool isAligned = (RI.getStackAlignment() >= 16) ||
     RI.needsStackRealignment(MF);
-  unsigned Opc = getStoreRegOpcode(RC, isAligned);
+  unsigned Opc = getStoreRegOpcode(SrcReg, RC, isAligned, TM);
   DebugLoc DL = DebugLoc::getUnknownLoc();
   MachineInstrBuilder MIB = BuildMI(MF, DL, get(Opc));
   for (unsigned i = 0, e = Addr.size(); i != e; ++i)
@@ -1860,8 +1889,10 @@ void X86InstrInfo::storeRegToAddr(MachineFunction &MF, unsigned SrcReg,
   NewMIs.push_back(MIB);
 }
 
-static unsigned getLoadRegOpcode(const TargetRegisterClass *RC,
-                                 bool isStackAligned) {
+static unsigned getLoadRegOpcode(unsigned DestReg,
+                                 const TargetRegisterClass *RC,
+                                 bool isStackAligned,
+                                 const TargetMachine &TM) {
   unsigned Opc = 0;
   if (RC == &X86::GR64RegClass) {
     Opc = X86::MOV64rm;
@@ -1870,15 +1901,26 @@ static unsigned getLoadRegOpcode(const TargetRegisterClass *RC,
   } else if (RC == &X86::GR16RegClass) {
     Opc = X86::MOV16rm;
   } else if (RC == &X86::GR8RegClass) {
-    Opc = X86::MOV8rm;
-  } else if (RC == &X86::GR64_RegClass) {
+    // Copying to or from a physical H register on x86-64 requires a NOREX
+    // move.  Otherwise use a normal move.
+    if (isHReg(DestReg) &&
+        TM.getSubtarget<X86Subtarget>().is64Bit())
+      Opc = X86::MOV8rm_NOREX;
+    else
+      Opc = X86::MOV8rm;
+  } else if (RC == &X86::GR64_ABCDRegClass) {
     Opc = X86::MOV64rm;
-  } else if (RC == &X86::GR32_RegClass) {
+  } else if (RC == &X86::GR32_ABCDRegClass) {
     Opc = X86::MOV32rm;
-  } else if (RC == &X86::GR16_RegClass) {
+  } else if (RC == &X86::GR16_ABCDRegClass) {
     Opc = X86::MOV16rm;
-  } else if (RC == &X86::GR8_RegClass) {
+  } else if (RC == &X86::GR8_ABCD_LRegClass) {
     Opc = X86::MOV8rm;
+  } else if (RC == &X86::GR8_ABCD_HRegClass) {
+    if (TM.getSubtarget<X86Subtarget>().is64Bit())
+      Opc = X86::MOV8rm_NOREX;
+    else
+      Opc = X86::MOV8rm;
   } else if (RC == &X86::GR64_NOREXRegClass) {
     Opc = X86::MOV64rm;
   } else if (RC == &X86::GR32_NOREXRegClass) {
@@ -1917,7 +1959,7 @@ void X86InstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
   const MachineFunction &MF = *MBB.getParent();
   bool isAligned = (RI.getStackAlignment() >= 16) ||
     RI.needsStackRealignment(MF);
-  unsigned Opc = getLoadRegOpcode(RC, isAligned);
+  unsigned Opc = getLoadRegOpcode(DestReg, RC, isAligned, TM);
   DebugLoc DL = DebugLoc::getUnknownLoc();
   if (MI != MBB.end()) DL = MI->getDebugLoc();
   addFrameReference(BuildMI(MBB, MI, DL, get(Opc), DestReg), FrameIdx);
@@ -1929,7 +1971,7 @@ void X86InstrInfo::loadRegFromAddr(MachineFunction &MF, unsigned DestReg,
                                  SmallVectorImpl<MachineInstr*> &NewMIs) const {
   bool isAligned = (RI.getStackAlignment() >= 16) ||
     RI.needsStackRealignment(MF);
-  unsigned Opc = getLoadRegOpcode(RC, isAligned);
+  unsigned Opc = getLoadRegOpcode(DestReg, RC, isAligned, TM);
   DebugLoc DL = DebugLoc::getUnknownLoc();
   MachineInstrBuilder MIB = BuildMI(MF, DL, get(Opc), DestReg);
   for (unsigned i = 0, e = Addr.size(); i != e; ++i)
@@ -2444,9 +2486,8 @@ X86InstrInfo::unfoldMemoryOperand(SelectionDAG &DAG, SDNode *N,
     MVT VT = *RC->vt_begin();
     bool isAligned = (RI.getStackAlignment() >= 16) ||
       RI.needsStackRealignment(MF);
-    Load = DAG.getTargetNode(getLoadRegOpcode(RC, isAligned), dl,
-                             VT, MVT::Other,
-                             &AddrOps[0], AddrOps.size());
+    Load = DAG.getTargetNode(getLoadRegOpcode(0, RC, isAligned, TM), dl,
+                             VT, MVT::Other, &AddrOps[0], AddrOps.size());
     NewNodes.push_back(Load);
   }
 
@@ -2478,8 +2519,10 @@ X86InstrInfo::unfoldMemoryOperand(SelectionDAG &DAG, SDNode *N,
     AddrOps.push_back(Chain);
     bool isAligned = (RI.getStackAlignment() >= 16) ||
       RI.needsStackRealignment(MF);
-    SDNode *Store = DAG.getTargetNode(getStoreRegOpcode(DstRC, isAligned), dl,
-                                      MVT::Other, &AddrOps[0], AddrOps.size());
+    SDNode *Store = DAG.getTargetNode(getStoreRegOpcode(0, DstRC,
+                                                        isAligned, TM),
+                                      dl, MVT::Other,
+                                      &AddrOps[0], AddrOps.size());
     NewNodes.push_back(Store);
   }
 
@@ -2768,8 +2811,8 @@ static unsigned getMemModRMByteSize(const MachineInstr &MI, unsigned Op,
   unsigned BaseReg = Base.getReg();
 
   // Is a SIB byte needed?
-  if ((!Is64BitMode || DispForReloc) && IndexReg.getReg() == 0 &&
-      (BaseReg == 0 || X86RegisterInfo::getX86RegNum(BaseReg) != N86::ESP)) {
+  if (IndexReg.getReg() == 0 && (!Is64BitMode || BaseReg != 0) && 
+      (BaseReg == 0 || X86RegisterInfo::getX86RegNum(BaseReg) != N86::ESP)) {      
     if (BaseReg == 0) {  // Just a displacement?
       // Emit special case [disp32] encoding
       ++FinalSize; 
@@ -2889,6 +2932,9 @@ static unsigned GetInstSizeWithDesc(const MachineInstr &MI,
   unsigned CurOp = 0;
   if (NumOps > 1 && Desc->getOperandConstraint(1, TOI::TIED_TO) != -1)
     CurOp++;
+  else if (NumOps > 2 && Desc->getOperandConstraint(NumOps-1, TOI::TIED_TO)== 0)
+    // Skip the last source operand that is tied_to the dest reg. e.g. LXADD32
+    --NumOps;
 
   switch (Desc->TSFlags & X86II::FormMask) {
   default: assert(0 && "Unknown FormMask value in X86 MachineCodeEmitter!");
@@ -2979,7 +3025,7 @@ static unsigned GetInstSizeWithDesc(const MachineInstr &MI,
   case X86II::MRMDestMem: {
     ++FinalSize;
     FinalSize += getMemModRMByteSize(MI, CurOp, IsPIC, Is64BitMode);
-    CurOp += 5;
+    CurOp +=  X86AddrNumOperands + 1;
     if (CurOp != NumOps) {
       ++CurOp;
       FinalSize += sizeConstant(X86InstrInfo::sizeOfImm(Desc));
@@ -2998,10 +3044,16 @@ static unsigned GetInstSizeWithDesc(const MachineInstr &MI,
     break;
 
   case X86II::MRMSrcMem: {
+    int AddrOperands;
+    if (Opcode == X86::LEA64r || Opcode == X86::LEA64_32r ||
+        Opcode == X86::LEA16r || Opcode == X86::LEA32r)
+      AddrOperands = X86AddrNumOperands - 1; // No segment register
+    else
+      AddrOperands = X86AddrNumOperands;
 
     ++FinalSize;
     FinalSize += getMemModRMByteSize(MI, CurOp+1, IsPIC, Is64BitMode);
-    CurOp += 5;
+    CurOp += AddrOperands + 1;
     if (CurOp != NumOps) {
       ++CurOp;
       FinalSize += sizeConstant(X86InstrInfo::sizeOfImm(Desc));
@@ -3014,8 +3066,14 @@ static unsigned GetInstSizeWithDesc(const MachineInstr &MI,
   case X86II::MRM4r: case X86II::MRM5r:
   case X86II::MRM6r: case X86II::MRM7r:
     ++FinalSize;
-    ++CurOp;
-    FinalSize += sizeRegModRMByte();
+    // Special handling of lfence and mfence. 
+    if (Desc->getOpcode() == X86::LFENCE ||
+        Desc->getOpcode() == X86::MFENCE)
+      FinalSize += sizeRegModRMByte();
+    else {
+      ++CurOp;
+      FinalSize += sizeRegModRMByte();
+    }
 
     if (CurOp != NumOps) {
       const MachineOperand &MO1 = MI.getOperand(CurOp++);
@@ -3045,7 +3103,7 @@ static unsigned GetInstSizeWithDesc(const MachineInstr &MI,
     
     ++FinalSize;
     FinalSize += getMemModRMByteSize(MI, CurOp, IsPIC, Is64BitMode);
-    CurOp += 4;
+    CurOp += X86AddrNumOperands;
 
     if (CurOp != NumOps) {
       const MachineOperand &MO = MI.getOperand(CurOp++);