[mips][msa] lowerMSABitClear() should use SelectionDAG::getNOT() instead of using...
[oota-llvm.git] / lib / Target / Mips / MipsConstantIslandPass.cpp
index 36b531487257d9ebad112003f0e8f0e10b5096f7..c46bbacf6585dedfe053abdabc58d83a91b3be55 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "Mips.h"
 #include "MCTargetDesc/MipsBaseInfo.h"
+#include "Mips16InstrInfo.h"
 #include "MipsMachineFunction.h"
 #include "MipsTargetMachine.h"
 #include "llvm/ADT/Statistic.h"
@@ -66,17 +67,16 @@ static cl::opt<int> ConstantIslandsSmallOffset(
   cl::desc("Make small offsets be this amount for testing purposes"),
   cl::Hidden);
 
-/// UnknownPadding - Return the worst case padding that could result from
-/// unknown offset bits.  This does not include alignment padding caused by
-/// known offset bits.
-///
-/// @param LogAlign log2(alignment)
-/// @param KnownBits Number of known low offset bits.
-static inline unsigned UnknownPadding(unsigned LogAlign, unsigned KnownBits) {
-  if (KnownBits < LogAlign)
-    return (1u << LogAlign) - (1u << KnownBits);
-  return 0;
-}
+//
+// For testing purposes we tell it to not use relaxed load forms so that it
+// will split blocks.
+//
+static cl::opt<bool> NoLoadRelaxation(
+  "mips-constant-islands-no-load-relaxation",
+  cl::init(false),
+  cl::desc("Don't relax loads to long loads - for testing purposes"),
+  cl::Hidden);
+
 
 namespace {
 
@@ -119,52 +119,15 @@ namespace {
       /// beginning of the block, or from an aligned jump table at the end.
       unsigned Size;
 
-      /// KnownBits - The number of low bits in Offset that are known to be
-      /// exact.  The remaining bits of Offset are an upper bound.
-      uint8_t KnownBits;
-
-      /// Unalign - When non-zero, the block contains instructions (inline asm)
-      /// of unknown size.  The real size may be smaller than Size bytes by a
-      /// multiple of 1 << Unalign.
-      uint8_t Unalign;
-
-      /// PostAlign - When non-zero, the block terminator contains a .align
-      /// directive, so the end of the block is aligned to 1 << PostAlign
-      /// bytes.
-      uint8_t PostAlign;
-
-      BasicBlockInfo() : Offset(0), Size(0), KnownBits(0), Unalign(0),
-        PostAlign(0) {}
-
-      /// Compute the number of known offset bits internally to this block.
-      /// This number should be used to predict worst case padding when
-      /// splitting the block.
-      unsigned internalKnownBits() const {
-        unsigned Bits = Unalign ? Unalign : KnownBits;
-        // If the block size isn't a multiple of the known bits, assume the
-        // worst case padding.
-        if (Size & ((1u << Bits) - 1))
-          Bits = countTrailingZeros(Size);
-        return Bits;
-      }
-
-      /// Compute the offset immediately following this block.  If LogAlign is
-      /// specified, return the offset the successor block will get if it has
-      /// this alignment.
+      // FIXME: ignore LogAlign for this patch
+      //
       unsigned postOffset(unsigned LogAlign = 0) const {
         unsigned PO = Offset + Size;
         return PO;
       }
 
-      /// Compute the number of known low bits of postOffset.  If this block
-      /// contains inline asm, the number of known bits drops to the
-      /// instruction alignment.  An aligned terminator may increase the number
-      /// of know bits.
-      /// If LogAlign is given, also consider the alignment of the next block.
-      unsigned postKnownBits(unsigned LogAlign = 0) const {
-        return std::max(std::max(unsigned(PostAlign), LogAlign),
-                        internalKnownBits());
-      }
+      BasicBlockInfo() : Offset(0), Size(0) {}
+
     };
 
     std::vector<BasicBlockInfo> BBInfo;
@@ -203,26 +166,25 @@ namespace {
       unsigned LongFormOpcode;
     public:
       bool NegOk;
-      bool IsSoImm;
-      bool KnownAlignment;
       CPUser(MachineInstr *mi, MachineInstr *cpemi, unsigned maxdisp,
-             bool neg, bool soimm,
+             bool neg,
              unsigned longformmaxdisp, unsigned longformopcode)
         : MI(mi), CPEMI(cpemi), MaxDisp(maxdisp),
           LongFormMaxDisp(longformmaxdisp), LongFormOpcode(longformopcode),
-          NegOk(neg), IsSoImm(soimm), KnownAlignment(false)  {
+          NegOk(neg){
         HighWaterMark = CPEMI->getParent();
       }
       /// getMaxDisp - Returns the maximum displacement supported by MI.
-      /// Correct for unknown alignment.
-      /// Conservatively subtract 2 bytes to handle weird alignment effects.
       unsigned getMaxDisp() const {
         unsigned xMaxDisp = ConstantIslandsSmallOffset?
                             ConstantIslandsSmallOffset: MaxDisp;
-        return (KnownAlignment ? xMaxDisp : xMaxDisp - 2) - 2;
+        return xMaxDisp;
+      }
+      void setMaxDisp(unsigned val) {
+        MaxDisp = val;
       }
       unsigned getLongFormMaxDisp() const {
-        return (KnownAlignment ? LongFormMaxDisp : LongFormMaxDisp - 2) - 2;
+        return LongFormMaxDisp;
       }
       unsigned getLongFormOpcode() const {
           return LongFormOpcode;
@@ -276,7 +238,7 @@ namespace {
   bool IsPIC;
   unsigned ABI;
   const MipsSubtarget *STI;
-  const MipsInstrInfo *TII;
+  const Mips16InstrInfo *TII;
   MipsFunctionInfo *MFI;
   MachineFunction *MF;
   MachineConstantPool *MCP;
@@ -318,7 +280,7 @@ namespace {
     void verify();
 
     bool isOffsetInRange(unsigned UserOffset, unsigned TrialOffset,
-                         unsigned Disp, bool NegativeOK, bool IsSoImm = false);
+                         unsigned Disp, bool NegativeOK);
     bool isOffsetInRange(unsigned UserOffset, unsigned TrialOffset,
                          const CPUser &U);
 
@@ -363,14 +325,14 @@ bool MipsConstantIslands::isLongFormOffsetInRange
   (unsigned UserOffset, unsigned TrialOffset,
    const CPUser &U) {
   return isOffsetInRange(UserOffset, TrialOffset,
-                         U.getLongFormMaxDisp(), U.NegOk, U.IsSoImm);
+                         U.getLongFormMaxDisp(), U.NegOk);
 }
 
 bool MipsConstantIslands::isOffsetInRange
   (unsigned UserOffset, unsigned TrialOffset,
    const CPUser &U) {
   return isOffsetInRange(UserOffset, TrialOffset,
-                         U.getMaxDisp(), U.NegOk, U.IsSoImm);
+                         U.getMaxDisp(), U.NegOk);
 }
 /// print block size and offset information - debugging
 void MipsConstantIslands::dumpBBs() {
@@ -378,9 +340,6 @@ void MipsConstantIslands::dumpBBs() {
     for (unsigned J = 0, E = BBInfo.size(); J !=E; ++J) {
       const BasicBlockInfo &BBI = BBInfo[J];
       dbgs() << format("%08x BB#%u\t", BBI.Offset, J)
-             << " kb=" << unsigned(BBI.KnownBits)
-             << " ua=" << unsigned(BBI.Unalign)
-             << " pa=" << unsigned(BBI.PostAlign)
              << format(" size=%#x\n", BBInfo[J].Size);
     }
   });
@@ -401,7 +360,7 @@ bool MipsConstantIslands::runOnMachineFunction(MachineFunction &mf) {
       !MipsSubtarget::useConstantIslands()) {
     return false;
   }
-  TII = (const MipsInstrInfo*)MF->getTarget().getInstrInfo();
+  TII = (const Mips16InstrInfo*)MF->getTarget().getInstrInfo();
   MFI = MF->getInfo<MipsFunctionInfo>();
   DEBUG(dbgs() << "constant island processing " << "\n");
   //
@@ -458,13 +417,11 @@ bool MipsConstantIslands::runOnMachineFunction(MachineFunction &mf) {
 
     DEBUG(dbgs() << "Beginning BR iteration #" << NoBRIters << '\n');
     bool BRChange = false;
-#ifdef IN_PROGRESS
     for (unsigned i = 0, e = ImmBranches.size(); i != e; ++i)
       BRChange |= fixupImmediateBr(ImmBranches[i]);
     if (BRChange && ++NoBRIters > 30)
       report_fatal_error("Branch Fix Up pass failed to converge!");
     DEBUG(dumpBBs());
-#endif
     if (!CPChange && !BRChange)
       break;
     MadeChange = true;
@@ -610,9 +567,6 @@ initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs) {
   for (MachineFunction::iterator I = MF->begin(), E = MF->end(); I != E; ++I)
     computeBlockSize(I);
 
-  // The known bits of the entry block offset are determined by the function
-  // alignment.
-  BBInfo.front().KnownBits = MF->getAlignment();
 
   // Compute block offsets.
   adjustBBOffsetsAfter(MF->begin());
@@ -637,18 +591,24 @@ initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs) {
         unsigned Bits = 0;
         unsigned Scale = 1;
         int UOpc = Opc;
-
         switch (Opc) {
         default:
-          continue;  // Ignore other JT branches
+          continue;  // Ignore other branches for now
+        case Mips::Bimm16:
+          Bits = 11;
+          Scale = 2;
+          isCond = false;
+          break;
+        case Mips::BimmX16:
+          Bits = 16;
+          Scale = 2;
+          isCond = false;
         }
         // Record this immediate branch.
         unsigned MaxOffs = ((1 << (Bits-1))-1) * Scale;
         ImmBranches.push_back(ImmBranch(I, MaxOffs, isCond, UOpc));
-
       }
 
-
       if (Opc == Mips::CONSTPOOL_ENTRY)
         continue;
 
@@ -664,7 +624,6 @@ initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs) {
           unsigned Bits = 0;
           unsigned Scale = 1;
           bool NegOk = false;
-          bool IsSoImm = false;
           unsigned LongFormBits = 0;
           unsigned LongFormScale = 0;
           unsigned LongFormOpcode = 0;
@@ -673,12 +632,15 @@ initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs) {
             llvm_unreachable("Unknown addressing mode for CP reference!");
           case Mips::LwRxPcTcp16:
             Bits = 8;
-            Scale = 2;
+            Scale = 4;
             LongFormOpcode = Mips::LwRxPcTcpX16;
+            LongFormBits = 16;
+            LongFormScale = 1;
             break;
           case Mips::LwRxPcTcpX16:
             Bits = 16;
-            Scale = 2;
+            Scale = 1;
+            NegOk = true;
             break;
           }
           // Remember that this is a user of a CP entry.
@@ -687,8 +649,7 @@ initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs) {
           unsigned MaxOffs = ((1 << Bits)-1) * Scale;
           unsigned LongFormMaxOffs = ((1 << LongFormBits)-1) * LongFormScale;
           CPUsers.push_back(CPUser(I, CPEMI, MaxOffs, NegOk,
-                                   IsSoImm, LongFormMaxOffs,
-                                   LongFormOpcode));
+                                   LongFormMaxOffs, LongFormOpcode));
 
           // Increment corresponding CPEntry reference count.
           CPEntry *CPE = findConstPoolEntry(CPI, CPEMI);
@@ -711,8 +672,6 @@ initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs) {
 void MipsConstantIslands::computeBlockSize(MachineBasicBlock *MBB) {
   BasicBlockInfo &BBI = BBInfo[MBB->getNumber()];
   BBI.Size = 0;
-  BBI.Unalign = 0;
-  BBI.PostAlign = 0;
 
   for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); I != E;
        ++I)
@@ -790,7 +749,7 @@ MachineBasicBlock *MipsConstantIslands::splitBlockBeforeInstr
   // Note the new unconditional branch is not being recorded.
   // There doesn't seem to be meaningful DebugInfo available; this doesn't
   // correspond to anything in the source.
-  BuildMI(OrigBB, DebugLoc(), TII->get(Mips::BimmX16)).addMBB(NewBB);
+  BuildMI(OrigBB, DebugLoc(), TII->get(Mips::Bimm16)).addMBB(NewBB);
   ++NumSplit;
 
   // Update the CFG.  All succs of OrigBB are now succs of NewBB.
@@ -844,21 +803,16 @@ MachineBasicBlock *MipsConstantIslands::splitBlockBeforeInstr
 /// isOffsetInRange - Checks whether UserOffset (the location of a constant pool
 /// reference) is within MaxDisp of TrialOffset (a proposed location of a
 /// constant pool entry).
-/// UserOffset is computed by getUserOffset above to include PC adjustments. If
-/// the mod 4 alignment of UserOffset is not known, the uncertainty must be
-/// subtracted from MaxDisp instead. CPUser::getMaxDisp() does that.
 bool MipsConstantIslands::isOffsetInRange(unsigned UserOffset,
                                          unsigned TrialOffset, unsigned MaxDisp,
-                                         bool NegativeOK, bool IsSoImm) {
+                                         bool NegativeOK) {
   if (UserOffset <= TrialOffset) {
     // User before the Trial.
     if (TrialOffset - UserOffset <= MaxDisp)
       return true;
-    // FIXME: Make use full range of soimm values.
   } else if (NegativeOK) {
     if (UserOffset - TrialOffset <= MaxDisp)
       return true;
-    // FIXME: Make use full range of soimm values.
   }
   return false;
 }
@@ -897,7 +851,7 @@ bool MipsConstantIslands::isWaterInRange(unsigned UserOffset,
     // the offset of the instruction. Also account for unknown alignment padding
     // in blocks between CPE and the user.
     if (CPEOffset < UserOffset)
-      UserOffset += Growth + UnknownPadding(MF->getAlignment(), CPELogAlign);
+      UserOffset += Growth;
   } else
     // CPE fits in existing padding.
     Growth = 0;
@@ -939,7 +893,7 @@ static bool BBIsJumpedOver(MachineBasicBlock *MBB) {
   MachineBasicBlock *Succ = *MBB->succ_begin();
   MachineBasicBlock *Pred = *MBB->pred_begin();
   MachineInstr *PredMI = &Pred->back();
-  if (PredMI->getOpcode() == Mips::BimmX16)
+  if (PredMI->getOpcode() == Mips::Bimm16)
     return PredMI->getOperand(0).getMBB() == Succ;
   return false;
 }
@@ -950,7 +904,7 @@ void MipsConstantIslands::adjustBBOffsetsAfter(MachineBasicBlock *BB) {
   for(unsigned i = BBNum + 1, e = MF->getNumBlockIDs(); i < e; ++i) {
     // Get the offset and known bits at the end of the layout predecessor.
     // Include the alignment of the current block.
-    unsigned Offset = BBInfo[i - 1].postOffset();
+    unsigned Offset = BBInfo[i - 1].Offset + BBInfo[i - 1].Size;
     BBInfo[i].Offset = Offset;
   }
 }
@@ -1044,6 +998,7 @@ int MipsConstantIslands::findLongFormInRangeCPEntry
                        true)) {
     DEBUG(dbgs() << "In range\n");
     UserMI->setDesc(TII->get(U.getLongFormOpcode()));
+    U.setMaxDisp(U.getLongFormMaxDisp());
     return 2;  // instruction is longer length now
   }
 
@@ -1083,6 +1038,8 @@ int MipsConstantIslands::findLongFormInRangeCPEntry
 /// the specific unconditional branch instruction.
 static inline unsigned getUnconditionalBrDisp(int Opc) {
   switch (Opc) {
+  case Mips::Bimm16:
+    return ((1<<10)-1)*2;
   case Mips::BimmX16:
     return ((1<<16)-1)*2;
   default:
@@ -1170,7 +1127,7 @@ void MipsConstantIslands::createNewWater(unsigned CPUserIndex,
       // but if the preceding conditional branch is out of range, the targets
       // will be exchanged, and the altered branch may be out of range, so the
       // machinery has to know about it.
-      int UncondBr = Mips::BimmX16;
+      int UncondBr = Mips::Bimm16;
       BuildMI(UserMBB, DebugLoc(), TII->get(UncondBr)).addMBB(NewMBB);
       unsigned MaxDisp = getUnconditionalBrDisp(UncondBr);
       ImmBranches.push_back(ImmBranch(&UserMBB->back(),
@@ -1188,9 +1145,7 @@ void MipsConstantIslands::createNewWater(unsigned CPUserIndex,
   // LogAlign which is the largest possible alignment in the function.
   unsigned LogAlign = MF->getAlignment();
   assert(LogAlign >= CPELogAlign && "Over-aligned constant pool entry");
-  unsigned KnownBits = UserBBI.internalKnownBits();
-  unsigned UPad = UnknownPadding(LogAlign, KnownBits);
-  unsigned BaseInsertOffset = UserOffset + U.getMaxDisp() - UPad;
+  unsigned BaseInsertOffset = UserOffset + U.getMaxDisp();
   DEBUG(dbgs() << format("Split in middle of big block before %#x",
                          BaseInsertOffset));
 
@@ -1200,19 +1155,17 @@ void MipsConstantIslands::createNewWater(unsigned CPUserIndex,
   BaseInsertOffset -= 4;
 
   DEBUG(dbgs() << format(", adjusted to %#x", BaseInsertOffset)
-               << " la=" << LogAlign
-               << " kb=" << KnownBits
-               << " up=" << UPad << '\n');
+               << " la=" << LogAlign << '\n');
 
   // This could point off the end of the block if we've already got constant
   // pool entries following this block; only the last one is in the water list.
   // Back past any possible branches (allow for a conditional and a maximally
   // long unconditional).
   if (BaseInsertOffset + 8 >= UserBBI.postOffset()) {
-    BaseInsertOffset = UserBBI.postOffset() - UPad - 8;
+    BaseInsertOffset = UserBBI.postOffset() - 8;
     DEBUG(dbgs() << format("Move inside block: %#x\n", BaseInsertOffset));
   }
-  unsigned EndInsertOffset = BaseInsertOffset + 4 + UPad +
+  unsigned EndInsertOffset = BaseInsertOffset + 4 +
     CPEMI->getOperand(2).getImm();
   MachineBasicBlock::iterator MI = UserMI;
   ++MI;
@@ -1285,9 +1238,10 @@ bool MipsConstantIslands::handleConstantPoolUser(unsigned CPUserIndex) {
     // No water found.
     // we first see if a longer form of the instrucion could have reached
     // the constant. in that case we won't bother to split
-#ifdef IN_PROGRESS
-    result = findLongFormInRangeCPEntry(U, UserOffset);
-#endif
+    if (!NoLoadRelaxation) {
+      result = findLongFormInRangeCPEntry(U, UserOffset);
+      if (result != 0) return true;
+    }
     DEBUG(dbgs() << "No water found\n");
     createNewWater(CPUserIndex, UserOffset, NewMBB);