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/ARM/ARMInstrInfo.cpp b/lib/Target/ARM/ARMInstrInfo.cpp
index 9ecd7c7..4d1819d 100644
--- a/lib/Target/ARM/ARMInstrInfo.cpp
+++ b/lib/Target/ARM/ARMInstrInfo.cpp
@@ -640,9 +640,10 @@
   return true;
 }
 
-MachineInstr *ARMInstrInfo::foldMemoryOperand(MachineInstr *MI,
-                                                 SmallVectorImpl<unsigned> &Ops,
-                                                 int FI) const {
+MachineInstr *ARMInstrInfo::foldMemoryOperand(MachineFunction &MF,
+                                              MachineInstr *MI,
+                                              SmallVectorImpl<unsigned> &Ops,
+                                              int FI) const {
   if (Ops.size() != 1) return NULL;
 
   unsigned OpNum = Ops[0];
@@ -721,7 +722,7 @@
 }
 
 bool ARMInstrInfo::canFoldMemoryOperand(MachineInstr *MI,
-                                         SmallVectorImpl<unsigned> &Ops) const {
+                                        SmallVectorImpl<unsigned> &Ops) const {
   if (Ops.size() != 1) return false;
 
   unsigned OpNum = Ops[0];
diff --git a/lib/Target/ARM/ARMInstrInfo.h b/lib/Target/ARM/ARMInstrInfo.h
index 60d9640..31216e4 100644
--- a/lib/Target/ARM/ARMInstrInfo.h
+++ b/lib/Target/ARM/ARMInstrInfo.h
@@ -191,11 +191,13 @@
                                            MachineBasicBlock::iterator MI,
                                  const std::vector<CalleeSavedInfo> &CSI) const;
   
-  virtual MachineInstr* foldMemoryOperand(MachineInstr* MI,
+  virtual MachineInstr* foldMemoryOperand(MachineFunction &MF,
+                                          MachineInstr* MI,
                                           SmallVectorImpl<unsigned> &Ops,
                                           int FrameIndex) const;
 
-  virtual MachineInstr* foldMemoryOperand(MachineInstr* MI,
+  virtual MachineInstr* foldMemoryOperand(MachineFunction &MF,
+                                          MachineInstr* MI,
                                           SmallVectorImpl<unsigned> &Ops,
                                           MachineInstr* LoadMI) const {
     return 0;
diff --git a/lib/Target/Alpha/AlphaInstrInfo.cpp b/lib/Target/Alpha/AlphaInstrInfo.cpp
index 53d7104..48e23f9 100644
--- a/lib/Target/Alpha/AlphaInstrInfo.cpp
+++ b/lib/Target/Alpha/AlphaInstrInfo.cpp
@@ -250,9 +250,10 @@
   NewMIs.push_back(MIB);
 }
 
-MachineInstr *AlphaInstrInfo::foldMemoryOperand(MachineInstr *MI,
-                                                 SmallVectorImpl<unsigned> &Ops,
-                                                 int FrameIndex) const {
+MachineInstr *AlphaInstrInfo::foldMemoryOperand(MachineFunction &MF,
+                                                MachineInstr *MI,
+                                                SmallVectorImpl<unsigned> &Ops,
+                                                int FrameIndex) const {
    if (Ops.size() != 1) return NULL;
 
    // Make sure this is a reg-reg copy.
diff --git a/lib/Target/Alpha/AlphaInstrInfo.h b/lib/Target/Alpha/AlphaInstrInfo.h
index 3477ae0..20d6388 100644
--- a/lib/Target/Alpha/AlphaInstrInfo.h
+++ b/lib/Target/Alpha/AlphaInstrInfo.h
@@ -67,11 +67,13 @@
                                const TargetRegisterClass *RC,
                                SmallVectorImpl<MachineInstr*> &NewMIs) const;
   
-  virtual MachineInstr* foldMemoryOperand(MachineInstr* MI,
+  virtual MachineInstr* foldMemoryOperand(MachineFunction &MF,
+                                          MachineInstr* MI,
                                           SmallVectorImpl<unsigned> &Ops,
                                           int FrameIndex) const;
 
-  virtual MachineInstr* foldMemoryOperand(MachineInstr* MI,
+  virtual MachineInstr* foldMemoryOperand(MachineFunction &MF,
+                                          MachineInstr* MI,
                                           SmallVectorImpl<unsigned> &Ops,
                                           MachineInstr* LoadMI) const {
     return 0;
diff --git a/lib/Target/CellSPU/SPUInstrInfo.cpp b/lib/Target/CellSPU/SPUInstrInfo.cpp
index ac9b9b8..64f6225 100644
--- a/lib/Target/CellSPU/SPUInstrInfo.cpp
+++ b/lib/Target/CellSPU/SPUInstrInfo.cpp
@@ -391,9 +391,10 @@
 /// foldMemoryOperand - SPU, like PPC, can only fold spills into
 /// copy instructions, turning them into load/store instructions.
 MachineInstr *
-SPUInstrInfo::foldMemoryOperand(MachineInstr *MI,
-                                   SmallVectorImpl<unsigned> &Ops,
-                                   int FrameIndex) const
+SPUInstrInfo::foldMemoryOperand(MachineFunction &MF,
+                                MachineInstr *MI,
+                                SmallVectorImpl<unsigned> &Ops,
+                                int FrameIndex) const
 {
 #if SOMEDAY_SCOTT_LOOKS_AT_ME_AGAIN
   if (Ops.size() != 1) return NULL;
diff --git a/lib/Target/CellSPU/SPUInstrInfo.h b/lib/Target/CellSPU/SPUInstrInfo.h
index 10c39a0..39237ee 100644
--- a/lib/Target/CellSPU/SPUInstrInfo.h
+++ b/lib/Target/CellSPU/SPUInstrInfo.h
@@ -77,12 +77,14 @@
                                  SmallVectorImpl<MachineInstr*> &NewMIs) const;
     
     //! Fold spills into load/store instructions
-    virtual MachineInstr* foldMemoryOperand(MachineInstr* MI,
+    virtual MachineInstr* foldMemoryOperand(MachineFunction &MF,
+                                            MachineInstr* MI,
                                             SmallVectorImpl<unsigned> &Ops,
                                             int FrameIndex) const;
 
     //! Fold any load/store to an operand
-    virtual MachineInstr* foldMemoryOperand(MachineInstr* MI,
+    virtual MachineInstr* foldMemoryOperand(MachineFunction &MF,
+                                            MachineInstr* MI,
                                             SmallVectorImpl<unsigned> &Ops,
                                             MachineInstr* LoadMI) const {
       return 0;
diff --git a/lib/Target/Mips/MipsInstrInfo.cpp b/lib/Target/Mips/MipsInstrInfo.cpp
index 85c1048..fa5d8b3 100644
--- a/lib/Target/Mips/MipsInstrInfo.cpp
+++ b/lib/Target/Mips/MipsInstrInfo.cpp
@@ -370,7 +370,8 @@
 }
 
 MachineInstr *MipsInstrInfo::
-foldMemoryOperand(MachineInstr* MI,
+foldMemoryOperand(MachineFunction &MF,
+                  MachineInstr* MI,
                   SmallVectorImpl<unsigned> &Ops, int FI) const 
 {
   if (Ops.size() != 1) return NULL;
diff --git a/lib/Target/Mips/MipsInstrInfo.h b/lib/Target/Mips/MipsInstrInfo.h
index 69ab795..d894b20 100644
--- a/lib/Target/Mips/MipsInstrInfo.h
+++ b/lib/Target/Mips/MipsInstrInfo.h
@@ -106,11 +106,13 @@
                                const TargetRegisterClass *RC,
                                SmallVectorImpl<MachineInstr*> &NewMIs) const;
   
-  virtual MachineInstr* foldMemoryOperand(MachineInstr* MI,
+  virtual MachineInstr* foldMemoryOperand(MachineFunction &MF,
+                                          MachineInstr* MI,
                                           SmallVectorImpl<unsigned> &Ops,
                                           int FrameIndex) const;
 
-  virtual MachineInstr* foldMemoryOperand(MachineInstr* MI,
+  virtual MachineInstr* foldMemoryOperand(MachineFunction &MF,
+                                          MachineInstr* MI,
                                           SmallVectorImpl<unsigned> &Ops,
                                           MachineInstr* LoadMI) const {
     return 0;
diff --git a/lib/Target/PowerPC/PPCInstrInfo.cpp b/lib/Target/PowerPC/PPCInstrInfo.cpp
index 47e2871..81c1003 100644
--- a/lib/Target/PowerPC/PPCInstrInfo.cpp
+++ b/lib/Target/PowerPC/PPCInstrInfo.cpp
@@ -536,7 +536,8 @@
 
 /// foldMemoryOperand - PowerPC (like most RISC's) can only fold spills into
 /// copy instructions, turning them into load/store instructions.
-MachineInstr *PPCInstrInfo::foldMemoryOperand(MachineInstr *MI,
+MachineInstr *PPCInstrInfo::foldMemoryOperand(MachineFunction &MF,
+                                              MachineInstr *MI,
                                               SmallVectorImpl<unsigned> &Ops,
                                               int FrameIndex) const {
   if (Ops.size() != 1) return NULL;
@@ -594,7 +595,7 @@
 }
 
 bool PPCInstrInfo::canFoldMemoryOperand(MachineInstr *MI,
-                                         SmallVectorImpl<unsigned> &Ops) const {
+                                        SmallVectorImpl<unsigned> &Ops) const {
   if (Ops.size() != 1) return false;
 
   // Make sure this is a reg-reg copy.  Note that we can't handle MCRF, because
diff --git a/lib/Target/PowerPC/PPCInstrInfo.h b/lib/Target/PowerPC/PPCInstrInfo.h
index 02d8bba..9f289e4 100644
--- a/lib/Target/PowerPC/PPCInstrInfo.h
+++ b/lib/Target/PowerPC/PPCInstrInfo.h
@@ -131,11 +131,13 @@
   
   /// foldMemoryOperand - PowerPC (like most RISC's) can only fold spills into
   /// copy instructions, turning them into load/store instructions.
-  virtual MachineInstr* foldMemoryOperand(MachineInstr* MI,
+  virtual MachineInstr* foldMemoryOperand(MachineFunction &MF,
+                                          MachineInstr* MI,
                                           SmallVectorImpl<unsigned> &Ops,
                                           int FrameIndex) const;
 
-  virtual MachineInstr* foldMemoryOperand(MachineInstr* MI,
+  virtual MachineInstr* foldMemoryOperand(MachineFunction &MF,
+                                          MachineInstr* MI,
                                           SmallVectorImpl<unsigned> &Ops,
                                           MachineInstr* LoadMI) const {
     return 0;
diff --git a/lib/Target/Sparc/SparcInstrInfo.cpp b/lib/Target/Sparc/SparcInstrInfo.cpp
index 56727bb..79fc912 100644
--- a/lib/Target/Sparc/SparcInstrInfo.cpp
+++ b/lib/Target/Sparc/SparcInstrInfo.cpp
@@ -222,9 +222,10 @@
   return;
 }
 
-MachineInstr *SparcInstrInfo::foldMemoryOperand(MachineInstr* MI,
-                                                 SmallVectorImpl<unsigned> &Ops,
-                                                 int FI) const {
+MachineInstr *SparcInstrInfo::foldMemoryOperand(MachineFunction &MF,
+                                                MachineInstr* MI,
+                                                SmallVectorImpl<unsigned> &Ops,
+                                                int FI) const {
   if (Ops.size() != 1) return NULL;
 
   unsigned OpNum = Ops[0];
diff --git a/lib/Target/Sparc/SparcInstrInfo.h b/lib/Target/Sparc/SparcInstrInfo.h
index 0ed7fab..14c3b4a 100644
--- a/lib/Target/Sparc/SparcInstrInfo.h
+++ b/lib/Target/Sparc/SparcInstrInfo.h
@@ -94,11 +94,13 @@
                                const TargetRegisterClass *RC,
                                SmallVectorImpl<MachineInstr*> &NewMIs) const;
   
-  virtual MachineInstr* foldMemoryOperand(MachineInstr* MI,
+  virtual MachineInstr* foldMemoryOperand(MachineFunction &MF,
+                                          MachineInstr* MI,
                                           SmallVectorImpl<unsigned> &Ops,
                                           int FrameIndex) const;
 
-  virtual MachineInstr* foldMemoryOperand(MachineInstr* MI,
+  virtual MachineInstr* foldMemoryOperand(MachineFunction &MF,
+                                          MachineInstr* MI,
                                           SmallVectorImpl<unsigned> &Ops,
                                           MachineInstr* LoadMI) const {
     return 0;
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()) {
diff --git a/lib/Target/X86/X86InstrInfo.h b/lib/Target/X86/X86InstrInfo.h
index 68f1664..4a62e9e 100644
--- a/lib/Target/X86/X86InstrInfo.h
+++ b/lib/Target/X86/X86InstrInfo.h
@@ -324,14 +324,16 @@
   /// folding and return true, otherwise it should return false.  If it folds
   /// the instruction, it is likely that the MachineInstruction the iterator
   /// references has been changed.
-  virtual MachineInstr* foldMemoryOperand(MachineInstr* MI,
+  virtual MachineInstr* foldMemoryOperand(MachineFunction &MF,
+                                          MachineInstr* MI,
                                           SmallVectorImpl<unsigned> &Ops,
                                           int FrameIndex) const;
 
   /// foldMemoryOperand - Same as the previous version except it allows folding
   /// of any load and store from / to any address, not just from a specific
   /// stack slot.
-  virtual MachineInstr* foldMemoryOperand(MachineInstr* MI,
+  virtual MachineInstr* foldMemoryOperand(MachineFunction &MF,
+                                          MachineInstr* MI,
                                   SmallVectorImpl<unsigned> &Ops,
                                   MachineInstr* LoadMI) const;