Fix pre- and post-indexed load / store encoding bugs.
[oota-llvm.git] / lib / Target / ARM / ARMConstantIslandPass.cpp
index 405ac0a2c685e1b5f2443e0a3f77949db85727f0..16de61524dffba6a07827a1354b5d9e7c2041522 100644 (file)
@@ -2,8 +2,8 @@
 //
 //                     The LLVM Compiler Infrastructure
 //
-// This file was developed by Chris Lattner and is distributed under the
-// University of Illinois Open Source License. See LICENSE.TXT for details.
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
 //
@@ -47,9 +47,6 @@ namespace {
   ///   CPE     - A constant pool entry that has been placed somewhere, which
   ///             tracks a list of users.
   class VISIBILITY_HIDDEN ARMConstantIslands : public MachineFunctionPass {
-    /// NextUID - Assign unique ID's to CPE's.
-    unsigned NextUID;
-
     /// BBSizes - The size of each MachineBasicBlock in bytes of code, indexed
     /// by MBB Number.  The two-byte pads required for Thumb alignment are
     /// counted as part of the following block (i.e., the offset and size for
@@ -112,7 +109,7 @@ namespace {
         : MI(mi), MaxDisp(maxdisp), isCond(cond), UncondBr(ubr) {}
     };
 
-    /// Branches - Keep track of all the immediate branch instructions.
+    /// ImmBranches - Keep track of all the immediate branch instructions.
     ///
     std::vector<ImmBranch> ImmBranches;
 
@@ -128,8 +125,8 @@ namespace {
     ARMFunctionInfo *AFI;
     bool isThumb;
   public:
-    static const char ID;
-    ARMConstantIslands() : MachineFunctionPass((intptr_t)&ID) {}
+    static char ID;
+    ARMConstantIslands() : MachineFunctionPass(&ID) {}
 
     virtual bool runOnMachineFunction(MachineFunction &Fn);
 
@@ -161,7 +158,7 @@ namespace {
                       MachineInstr *CPEMI, unsigned Disp,
                       bool DoDump);
     bool WaterIsInRange(unsigned UserOffset, MachineBasicBlock *Water,
-                        unsigned Disp);
+                        CPUser &U);
     bool OffsetIsInRange(unsigned UserOffset, unsigned TrialOffset,
                         unsigned Disp, bool NegativeOK);
     bool BBIsInRange(MachineInstr *MI, MachineBasicBlock *BB, unsigned Disp);
@@ -174,7 +171,7 @@ namespace {
     void dumpBBs();
     void verify(MachineFunction &Fn);
   };
-  const char ARMConstantIslands::ID = 0;
+  char ARMConstantIslands::ID = 0;
 }
 
 /// verify - check BBOffsets, BBSizes, alignment of islands
@@ -199,8 +196,8 @@ void ARMConstantIslands::verify(MachineFunction &Fn) {
 /// print block size and offset information - debugging
 void ARMConstantIslands::dumpBBs() {
   for (unsigned J = 0, E = BBOffsets.size(); J !=E; ++J) {
-    DOUT << "block" << J << " offset" << BBOffsets[J] << 
-                            " size" << BBSizes[J] << "\n";
+    DOUT << "block " << J << " offset " << BBOffsets[J] << 
+                            " size " << BBSizes[J] << "\n";
   }
 }
 
@@ -237,7 +234,7 @@ bool ARMConstantIslands::runOnMachineFunction(MachineFunction &Fn) {
   }
   
   /// The next UID to take is the first unused one.
-  NextUID = CPEMIs.size();
+  AFI->initConstPoolEntryUId(CPEMIs.size());
   
   // Do the initial scan of the function, building up information about the
   // sizes of each block, the location of all the water, and finding all of the
@@ -288,8 +285,8 @@ bool ARMConstantIslands::runOnMachineFunction(MachineFunction &Fn) {
 void ARMConstantIslands::DoInitialPlacement(MachineFunction &Fn,
                                         std::vector<MachineInstr*> &CPEMIs){
   // Create the basic block to hold the CPE's.
-  MachineBasicBlock *BB = new MachineBasicBlock();
-  Fn.getBasicBlockList().push_back(BB);
+  MachineBasicBlock *BB = Fn.CreateMachineBasicBlock();
+  Fn.push_back(BB);
   
   // Add all of the constants from the constant pool to the end block, use an
   // identity mapping of CPI's to CPE's.
@@ -298,7 +295,7 @@ void ARMConstantIslands::DoInitialPlacement(MachineFunction &Fn,
   
   const TargetData &TD = *Fn.getTarget().getTargetData();
   for (unsigned i = 0, e = CPs.size(); i != e; ++i) {
-    unsigned Size = TD.getTypeSize(CPs[i].getType());
+    unsigned Size = TD.getABITypeSize(CPs[i].getType());
     // Verify that all constant pool entries are a multiple of 4 bytes.  If not,
     // we would have to pad them out or something so that instructions stay
     // aligned.
@@ -368,10 +365,10 @@ void ARMConstantIslands::InitialFunctionScan(MachineFunction &Fn,
     for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
          I != E; ++I) {
       // Add instruction size to MBBSize.
-      MBBSize += ARM::GetInstSize(I);
+      MBBSize += TII->GetInstSizeInBytes(I);
 
       int Opc = I->getOpcode();
-      if (TII->isBranch(Opc)) {
+      if (I->getDesc().isBranch()) {
         bool isCond = false;
         unsigned Bits = 0;
         unsigned Scale = 1;
@@ -416,14 +413,14 @@ void ARMConstantIslands::InitialFunctionScan(MachineFunction &Fn,
 
       // Scan the instructions for constant pool operands.
       for (unsigned op = 0, e = I->getNumOperands(); op != e; ++op)
-        if (I->getOperand(op).isConstantPoolIndex()) {
+        if (I->getOperand(op).isCPI()) {
           // We found one.  The addressing mode tells us the max displacement
           // from the PC that this instruction permits.
           
           // Basic size info comes from the TSFlags field.
           unsigned Bits = 0;
           unsigned Scale = 1;
-          unsigned TSFlags = I->getInstrDescriptor()->TSFlags;
+          unsigned TSFlags = I->getDesc().TSFlags;
           switch (TSFlags & ARMII::AddrModeMask) {
           default: 
             // Constant pool entries can reach anything.
@@ -467,7 +464,7 @@ void ARMConstantIslands::InitialFunctionScan(MachineFunction &Fn,
           }
 
           // Remember that this is a user of a CP entry.
-          unsigned CPI = I->getOperand(op).getConstantPoolIndex();
+          unsigned CPI = I->getOperand(op).getIndex();
           MachineInstr *CPEMI = CPEMIs[CPI];
           unsigned MaxOffs = ((1 << Bits)-1) * Scale;          
           CPUsers.push_back(CPUser(I, CPEMI, MaxOffs));
@@ -519,7 +516,7 @@ unsigned ARMConstantIslands::GetOffsetOf(MachineInstr *MI) const {
   for (MachineBasicBlock::iterator I = MBB->begin(); ; ++I) {
     assert(I != MBB->end() && "Didn't find MI in its own basic block?");
     if (&*I == MI) return Offset;
-    Offset += ARM::GetInstSize(I);
+    Offset += TII->GetInstSizeInBytes(I);
   }
 }
 
@@ -558,11 +555,12 @@ void ARMConstantIslands::UpdateForInsertedWaterBlock(MachineBasicBlock *NewBB) {
 /// account for this change and returns the newly created block.
 MachineBasicBlock *ARMConstantIslands::SplitBlockBeforeInstr(MachineInstr *MI) {
   MachineBasicBlock *OrigBB = MI->getParent();
+  MachineFunction &MF = *OrigBB->getParent();
 
   // Create a new MBB for the code after the OrigBB.
-  MachineBasicBlock *NewBB = new MachineBasicBlock(OrigBB->getBasicBlock());
+  MachineBasicBlock *NewBB = MF.CreateMachineBasicBlock(OrigBB->getBasicBlock());
   MachineFunction::iterator MBBI = OrigBB; ++MBBI;
-  OrigBB->getParent()->getBasicBlockList().insert(MBBI, NewBB);
+  MF.insert(MBBI, NewBB);
   
   // Splice the instructions starting with MI over to NewBB.
   NewBB->splice(NewBB->end(), OrigBB, MI, OrigBB->end());
@@ -590,7 +588,7 @@ MachineBasicBlock *ARMConstantIslands::SplitBlockBeforeInstr(MachineInstr *MI) {
   // Update internal data structures to account for the newly inserted MBB.
   // This is almost the same as UpdateForInsertedWaterBlock, except that
   // the Water goes after OrigBB, not NewBB.
-  NewBB->getParent()->RenumberBlocks(NewBB);
+  MF.RenumberBlocks(NewBB);
   
   // Insert a size into BBSizes to align it properly with the (newly
   // renumbered) block numbers.
@@ -617,7 +615,7 @@ MachineBasicBlock *ARMConstantIslands::SplitBlockBeforeInstr(MachineInstr *MI) {
   unsigned NewBBSize = 0;
   for (MachineBasicBlock::iterator I = NewBB->begin(), E = NewBB->end();
        I != E; ++I)
-    NewBBSize += ARM::GetInstSize(I);
+    NewBBSize += TII->GetInstSizeInBytes(I);
   
   unsigned OrigBBI = OrigBB->getNumber();
   unsigned NewBBI = NewBB->getNumber();
@@ -668,8 +666,9 @@ bool ARMConstantIslands::OffsetIsInRange(unsigned UserOffset,
 /// Water (a basic block) will be in range for the specific MI.
 
 bool ARMConstantIslands::WaterIsInRange(unsigned UserOffset,
-                         MachineBasicBlock* Water, unsigned MaxDisp)
+                         MachineBasicBlock* Water, CPUser &U)
 {
+  unsigned MaxDisp = U.MaxDisp;
   MachineFunction::iterator I = next(MachineFunction::iterator(Water));
   unsigned CPEOffset = BBOffsets[Water->getNumber()] + 
                        BBSizes[Water->getNumber()];
@@ -678,7 +677,7 @@ bool ARMConstantIslands::WaterIsInRange(unsigned UserOffset,
   // the offset of the instruction.  (Currently applies only to ARM, so
   // no alignment compensation attempted here.)
   if (CPEOffset < UserOffset)
-    UserOffset += 4;
+    UserOffset += U.CPEMI->getOperand(2).getImm();
 
   return OffsetIsInRange (UserOffset, CPEOffset, MaxDisp, !isThumb);
 }
@@ -739,14 +738,11 @@ void ARMConstantIslands::AdjustBBOffsetsAfter(MachineBasicBlock *BB,
             delta -= 2;
           }
         }
-        // Thumb jump tables require padding.  They can be at the end, or
-        // followed by an unconditional branch.
+        // Thumb jump tables require padding.  They should be at the end;
+        // following unconditional branches are removed by AnalyzeBranch.
         MachineInstr *ThumbJTMI = NULL;
         if (prior(MBB->end())->getOpcode() == ARM::tBR_JTr)
           ThumbJTMI = prior(MBB->end());
-        else if (prior(MBB->end()) != MBB->begin() &&
-                prior(prior(MBB->end()))->getOpcode() == ARM::tBR_JTr)
-          ThumbJTMI = prior(prior(MBB->end()));
         if (ThumbJTMI) {
           unsigned newMIOffset = GetOffsetOf(ThumbJTMI);
           unsigned oldMIOffset = newMIOffset - delta;
@@ -804,7 +800,7 @@ int ARMConstantIslands::LookForExistingCPEntry(CPUser& U, unsigned UserOffset)
   }
 
   // No.  Look for previously created clones of the CPE that are in range.
-  unsigned CPI = CPEMI->getOperand(1).getConstantPoolIndex();
+  unsigned CPI = CPEMI->getOperand(1).getIndex();
   std::vector<CPEntry> &CPEs = CPEntries[CPI];
   for (unsigned i = 0, e = CPEs.size(); i != e; ++i) {
     // We already tried this one
@@ -819,8 +815,8 @@ int ARMConstantIslands::LookForExistingCPEntry(CPUser& U, unsigned UserOffset)
       U.CPEMI = CPEs[i].CPEMI;
       // Change the CPI in the instruction operand to refer to the clone.
       for (unsigned j = 0, e = UserMI->getNumOperands(); j != e; ++j)
-        if (UserMI->getOperand(j).isConstantPoolIndex()) {
-          UserMI->getOperand(j).setConstantPoolIndex(CPEs[i].CPI);
+        if (UserMI->getOperand(j).isCPI()) {
+          UserMI->getOperand(j).setIndex(CPEs[i].CPI);
           break;
         }
       // Adjust the refcount of the clone...
@@ -869,7 +865,7 @@ bool ARMConstantIslands::LookForWater(CPUser &U, unsigned UserOffset,
     for (std::vector<MachineBasicBlock*>::iterator IP = prior(WaterList.end()),
         B = WaterList.begin();; --IP) {
       MachineBasicBlock* WaterBB = *IP;
-      if (WaterIsInRange(UserOffset, WaterBB, U.MaxDisp)) {
+      if (WaterIsInRange(UserOffset, WaterBB, U)) {
         if (isThumb &&
             (BBOffsets[WaterBB->getNumber()] + 
              BBSizes[WaterBB->getNumber()])%4 != 0) {
@@ -970,9 +966,9 @@ void ARMConstantIslands::CreateNewWater(unsigned CPUserIndex,
     MachineBasicBlock::iterator MI = UserMI;
     ++MI;
     unsigned CPUIndex = CPUserIndex+1;
-    for (unsigned Offset = UserOffset+ARM::GetInstSize(UserMI);
+    for (unsigned Offset = UserOffset+TII->GetInstSizeInBytes(UserMI);
          Offset < BaseInsertOffset;
-         Offset += ARM::GetInstSize(MI),
+         Offset += TII->GetInstSizeInBytes(MI),
             MI = next(MI)) {
       if (CPUIndex < CPUsers.size() && CPUsers[CPUIndex].MI == MI) {
         if (!OffsetIsInRange(Offset, EndInsertOffset, 
@@ -1000,7 +996,7 @@ bool ARMConstantIslands::HandleConstantPoolUser(MachineFunction &Fn,
   CPUser &U = CPUsers[CPUserIndex];
   MachineInstr *UserMI = U.MI;
   MachineInstr *CPEMI  = U.CPEMI;
-  unsigned CPI = CPEMI->getOperand(1).getConstantPoolIndex();
+  unsigned CPI = CPEMI->getOperand(1).getIndex();
   unsigned Size = CPEMI->getOperand(2).getImm();
   MachineBasicBlock *NewMBB;
   // Compute this only once, it's expensive.  The 4 or 8 is the value the
@@ -1020,7 +1016,7 @@ bool ARMConstantIslands::HandleConstantPoolUser(MachineFunction &Fn,
 
   // No existing clone of this CPE is within range.
   // We will be generating a new clone.  Get a UID for it.
-  unsigned ID  = NextUID++;
+  unsigned ID  = AFI->createConstPoolEntryUId();
 
   // Look for water where we can place this CPE.  We look for the farthest one
   // away that will work.  Forward references only for now (although later
@@ -1033,8 +1029,8 @@ bool ARMConstantIslands::HandleConstantPoolUser(MachineFunction &Fn,
   }
 
   // Okay, we know we can put an island before NewMBB now, do it!
-  MachineBasicBlock *NewIsland = new MachineBasicBlock();
-  Fn.getBasicBlockList().insert(NewMBB, NewIsland);
+  MachineBasicBlock *NewIsland = Fn.CreateMachineBasicBlock();
+  Fn.insert(NewMBB, NewIsland);
 
   // Update internal data structures to account for the newly inserted MBB.
   UpdateForInsertedWaterBlock(NewIsland);
@@ -1059,8 +1055,8 @@ bool ARMConstantIslands::HandleConstantPoolUser(MachineFunction &Fn,
   
   // Finally, change the CPI in the instruction operand to be ID.
   for (unsigned i = 0, e = UserMI->getNumOperands(); i != e; ++i)
-    if (UserMI->getOperand(i).isConstantPoolIndex()) {
-      UserMI->getOperand(i).setConstantPoolIndex(ID);
+    if (UserMI->getOperand(i).isCPI()) {
+      UserMI->getOperand(i).setIndex(ID);
       break;
     }
       
@@ -1141,7 +1137,7 @@ bool ARMConstantIslands::BBIsInRange(MachineInstr *MI,MachineBasicBlock *DestBB,
 /// away to fit in its displacement field.
 bool ARMConstantIslands::FixUpImmediateBr(MachineFunction &Fn, ImmBranch &Br) {
   MachineInstr *MI = Br.MI;
-  MachineBasicBlock *DestBB = MI->getOperand(0).getMachineBasicBlock();
+  MachineBasicBlock *DestBB = MI->getOperand(0).getMBB();
 
   // Check to see if the DestBB is already in-range.
   if (BBIsInRange(MI, DestBB, Br.MaxDisp))
@@ -1164,7 +1160,7 @@ ARMConstantIslands::FixUpUnconditionalBr(MachineFunction &Fn, ImmBranch &Br) {
 
   // Use BL to implement far jump.
   Br.MaxDisp = (1 << 21) * 2;
-  MI->setInstrDescriptor(TII->get(ARM::tBfar));
+  MI->setDesc(TII->get(ARM::tBfar));
   BBSizes[MBB->getNumber()] += 2;
   AdjustBBOffsetsAfter(MBB, 2);
   HasFarJump = true;
@@ -1181,7 +1177,7 @@ ARMConstantIslands::FixUpUnconditionalBr(MachineFunction &Fn, ImmBranch &Br) {
 bool
 ARMConstantIslands::FixUpConditionalBr(MachineFunction &Fn, ImmBranch &Br) {
   MachineInstr *MI = Br.MI;
-  MachineBasicBlock *DestBB = MI->getOperand(0).getMachineBasicBlock();
+  MachineBasicBlock *DestBB = MI->getOperand(0).getMBB();
 
   // Add a unconditional branch to the destination and invert the branch
   // condition to jump over it:
@@ -1190,8 +1186,9 @@ ARMConstantIslands::FixUpConditionalBr(MachineFunction &Fn, ImmBranch &Br) {
   // bge L2
   // b   L1
   // L2:
-  ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(1).getImmedValue();
+  ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(1).getImm();
   CC = ARMCC::getOppositeCondition(CC);
+  unsigned CCReg = MI->getOperand(2).getReg();
 
   // If the branch is at the end of its MBB and that has a fall-through block,
   // direct the updated conditional branch to the fall-through block. Otherwise,
@@ -1202,7 +1199,7 @@ ARMConstantIslands::FixUpConditionalBr(MachineFunction &Fn, ImmBranch &Br) {
 
   NumCBrFixed++;
   if (BMI != MI) {
-    if (next(MachineBasicBlock::iterator(MI)) == MBB->back() &&
+    if (next(MachineBasicBlock::iterator(MI)) == prior(MBB->end()) &&
         BMI->getOpcode() == Br.UncondBr) {
       // Last MI in the BB is a unconditional branch. Can we simply invert the
       // condition and swap destinations:
@@ -1211,11 +1208,11 @@ ARMConstantIslands::FixUpConditionalBr(MachineFunction &Fn, ImmBranch &Br) {
       // =>
       // bne L2
       // b   L1
-      MachineBasicBlock *NewDest = BMI->getOperand(0).getMachineBasicBlock();
+      MachineBasicBlock *NewDest = BMI->getOperand(0).getMBB();
       if (BBIsInRange(MI, NewDest, Br.MaxDisp)) {
         DOUT << "  Invert Bcc condition and swap its destination with " << *BMI;
-        BMI->getOperand(0).setMachineBasicBlock(DestBB);
-        MI->getOperand(0).setMachineBasicBlock(NewDest);
+        BMI->getOperand(0).setMBB(DestBB);
+        MI->getOperand(0).setMBB(NewDest);
         MI->getOperand(1).setImm(CC);
         return true;
       }
@@ -1226,7 +1223,7 @@ ARMConstantIslands::FixUpConditionalBr(MachineFunction &Fn, ImmBranch &Br) {
     SplitBlockBeforeInstr(MI);
     // No need for the branch to the next block. We're adding a unconditional
     // branch to the destination.
-    int delta = ARM::GetInstSize(&MBB->back());
+    int delta = TII->GetInstSizeInBytes(&MBB->back());
     BBSizes[MBB->getNumber()] -= delta;
     MachineBasicBlock* SplitBB = next(MachineFunction::iterator(MBB));
     AdjustBBOffsetsAfter(SplitBB, -delta);
@@ -1241,20 +1238,21 @@ ARMConstantIslands::FixUpConditionalBr(MachineFunction &Fn, ImmBranch &Br) {
 
   // Insert a new conditional branch and a new unconditional branch.
   // Also update the ImmBranch as well as adding a new entry for the new branch.
-  BuildMI(MBB, TII->get(MI->getOpcode())).addMBB(NextBB).addImm(CC);
+  BuildMI(MBB, TII->get(MI->getOpcode())).addMBB(NextBB)
+    .addImm(CC).addReg(CCReg);
   Br.MI = &MBB->back();
-  BBSizes[MBB->getNumber()] += ARM::GetInstSize(&MBB->back());
+  BBSizes[MBB->getNumber()] += TII->GetInstSizeInBytes(&MBB->back());
   BuildMI(MBB, TII->get(Br.UncondBr)).addMBB(DestBB);
-  BBSizes[MBB->getNumber()] += ARM::GetInstSize(&MBB->back());
+  BBSizes[MBB->getNumber()] += TII->GetInstSizeInBytes(&MBB->back());
   unsigned MaxDisp = getUnconditionalBrDisp(Br.UncondBr);
   ImmBranches.push_back(ImmBranch(&MBB->back(), MaxDisp, false, Br.UncondBr));
 
   // Remove the old conditional branch.  It may or may not still be in MBB.
-  BBSizes[MI->getParent()->getNumber()] -= ARM::GetInstSize(MI);
+  BBSizes[MI->getParent()->getNumber()] -= TII->GetInstSizeInBytes(MI);
   MI->eraseFromParent();
 
   // The net size change is an addition of one unconditional branch.
-  int delta = ARM::GetInstSize(&MBB->back());
+  int delta = TII->GetInstSizeInBytes(&MBB->back());
   AdjustBBOffsetsAfter(MBB, delta);
   return true;
 }
@@ -1265,12 +1263,12 @@ bool ARMConstantIslands::UndoLRSpillRestore() {
   bool MadeChange = false;
   for (unsigned i = 0, e = PushPopMIs.size(); i != e; ++i) {
     MachineInstr *MI = PushPopMIs[i];
-    if (MI->getNumOperands() == 1) {
-        if (MI->getOpcode() == ARM::tPOP_RET &&
-            MI->getOperand(0).getReg() == ARM::PC)
-          BuildMI(MI->getParent(), TII->get(ARM::tBX_RET));
-        MI->eraseFromParent();
-        MadeChange = true;
+    if (MI->getOpcode() == ARM::tPOP_RET &&
+        MI->getOperand(0).getReg() == ARM::PC &&
+        MI->getNumExplicitOperands() == 1) {
+      BuildMI(MI->getParent(), TII->get(ARM::tBX_RET));
+      MI->eraseFromParent();
+      MadeChange = true;
     }
   }
   return MadeChange;