It's not always safe to fold movsd into xorpd, etc. Check the alignment of the load address first to make sure it's 16 byte aligned.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@46893 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/X86/X86InstrInfo.cpp b/lib/Target/X86/X86InstrInfo.cpp
index 0c9a5c6..42c994a 100644
--- a/lib/Target/X86/X86InstrInfo.cpp
+++ b/lib/Target/X86/X86InstrInfo.cpp
@@ -1670,7 +1670,7 @@
 
 MachineInstr*
 X86InstrInfo::foldMemoryOperand(MachineInstr *MI, unsigned i,
-                                   SmallVector<MachineOperand,4> &MOs) const {
+                                SmallVector<MachineOperand,4> &MOs) const {
   const DenseMap<unsigned*, unsigned> *OpcodeTablePtr = NULL;
   bool isTwoAddrFold = false;
   unsigned NumOps = MI->getDesc().getNumOperands();
@@ -1730,12 +1730,33 @@
 }
 
 
-MachineInstr* X86InstrInfo::foldMemoryOperand(MachineInstr *MI,
+MachineInstr* X86InstrInfo::foldMemoryOperand(MachineFunction &MF,
+                                              MachineInstr *MI,
                                               SmallVectorImpl<unsigned> &Ops,
                                               int FrameIndex) const {
   // Check switch flag 
   if (NoFusing) return NULL;
 
+  const MachineFrameInfo *MFI = MF.getFrameInfo();
+  unsigned Alignment = MFI->getObjectAlignment(FrameIndex);
+  // FIXME: Move alignment requirement into tables?
+  if (Alignment < 16) {
+    switch (MI->getOpcode()) {
+    default: break;
+    // Not always safe to fold movsd into these instructions since their load
+    // folding variants expects the address to be 16 byte aligned.
+    case X86::FsANDNPDrr:
+    case X86::FsANDNPSrr:
+    case X86::FsANDPDrr:
+    case X86::FsANDPSrr:
+    case X86::FsORPDrr:
+    case X86::FsORPSrr:
+    case X86::FsXORPDrr:
+    case X86::FsXORPSrr:
+      return NULL;
+    }
+  }
+
   if (Ops.size() == 2 && Ops[0] == 0 && Ops[1] == 1) {
     unsigned NewOpc = 0;
     switch (MI->getOpcode()) {
@@ -1756,12 +1777,39 @@
   return foldMemoryOperand(MI, Ops[0], MOs);
 }
 
-MachineInstr* X86InstrInfo::foldMemoryOperand(MachineInstr *MI,
+MachineInstr* X86InstrInfo::foldMemoryOperand(MachineFunction &MF,
+                                              MachineInstr *MI,
                                               SmallVectorImpl<unsigned> &Ops,
                                               MachineInstr *LoadMI) const {
   // Check switch flag 
   if (NoFusing) return NULL;
 
+  unsigned Alignment = 0;
+  for (unsigned i = 0, e = LoadMI->getNumMemOperands(); i != e; ++i) {
+    const MemOperand &MRO = LoadMI->getMemOperand(i);
+    unsigned Align = MRO.getAlignment();
+    if (Align > Alignment)
+      Alignment = Align;
+  }
+
+  // FIXME: Move alignment requirement into tables?
+  if (Alignment < 16) {
+    switch (MI->getOpcode()) {
+    default: break;
+    // Not always safe to fold movsd into these instructions since their load
+    // folding variants expects the address to be 16 byte aligned.
+    case X86::FsANDNPDrr:
+    case X86::FsANDNPSrr:
+    case X86::FsANDPDrr:
+    case X86::FsANDPSrr:
+    case X86::FsORPDrr:
+    case X86::FsORPSrr:
+    case X86::FsXORPDrr:
+    case X86::FsXORPSrr:
+      return NULL;
+    }
+  }
+
   if (Ops.size() == 2 && Ops[0] == 0 && Ops[1] == 1) {
     unsigned NewOpc = 0;
     switch (MI->getOpcode()) {