[llvm-commits] [llvm] r111585 - in /llvm/trunk: include/llvm/Target/TargetRegisterInfo.h lib/CodeGen/LocalStackSlotAllocation.cpp lib/Target/ARM/ARMBaseRegisterInfo.cpp lib/Target/ARM/ARMBaseRegisterInfo.h

Jim Grosbach grosbach at apple.com
Thu Aug 19 16:52:25 PDT 2010


Author: grosbach
Date: Thu Aug 19 18:52:25 2010
New Revision: 111585

URL: http://llvm.org/viewvc/llvm-project?rev=111585&view=rev
Log:
Better handling of offsets on frame index references. rdar://8277890

Modified:
    llvm/trunk/include/llvm/Target/TargetRegisterInfo.h
    llvm/trunk/lib/CodeGen/LocalStackSlotAllocation.cpp
    llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.cpp
    llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.h

Modified: llvm/trunk/include/llvm/Target/TargetRegisterInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetRegisterInfo.h?rev=111585&r1=111584&r2=111585&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Target/TargetRegisterInfo.h (original)
+++ llvm/trunk/include/llvm/Target/TargetRegisterInfo.h Thu Aug 19 18:52:25 2010
@@ -636,6 +636,12 @@
     return false;
   }
 
+  /// getFrameIndexInstrOffset - Get the offset from the referenced frame
+  /// index in the instruction, if the is one.
+  virtual int64_t getFrameIndexInstrOffset(MachineInstr *MI, int Idx) const {
+    return 0;
+  }
+
   /// needsFrameBaseReg - Returns true if the instruction's frame index
   /// reference would be better served by a base register other than FP
   /// or SP. Used by LocalStackFrameAllocation to determine which frame index
@@ -647,8 +653,8 @@
   /// materializeFrameBaseRegister - Insert defining instruction(s) for
   /// BaseReg to be a pointer to FrameIdx before insertion point I.
   virtual void materializeFrameBaseRegister(MachineBasicBlock::iterator I,
-                                            unsigned BaseReg,
-                                            int FrameIdx) const {
+                                            unsigned BaseReg, int FrameIdx,
+                                            int64_t Offset) const {
     assert(0 && "materializeFrameBaseRegister does not exist on this target");
   }
 
@@ -659,11 +665,11 @@
     assert(0 && "resolveFrameIndex does not exist on this target");
   }
 
-  /// isBaseRegInRange - Determine whether a given base register definition
-  /// is in range to resolve a frame index.
-  virtual bool isBaseRegInRange(const MachineInstr *MI, unsigned Reg,
-                                int64_t Offset) const {
-    assert(0 && "isBaseRegInRange does not exist on this target");
+  /// isFrameOffsetLegal - Determine whether a given offset immediate is
+  /// encodable to resolve a frame index.
+  virtual bool isFrameOffsetLegal(const MachineInstr *MI,
+                                  int64_t Offset) const {
+    assert(0 && "isFrameOffsetLegal does not exist on this target");
     return false; // Must return a value in order to compile with VS 2005
   }
 

Modified: llvm/trunk/lib/CodeGen/LocalStackSlotAllocation.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LocalStackSlotAllocation.cpp?rev=111585&r1=111584&r2=111585&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/LocalStackSlotAllocation.cpp (original)
+++ llvm/trunk/lib/CodeGen/LocalStackSlotAllocation.cpp Thu Aug 19 18:52:25 2010
@@ -182,7 +182,7 @@
     // Check if the relative offset from the where the base register references
     // to the target address is in range for the instruction.
     int64_t Offset = LocalFrameOffset - RegOffset.second;
-    if (TRI->isBaseRegInRange(MI, RegOffset.first, Offset))
+    if (TRI->isFrameOffsetLegal(MI, Offset))
       return true;
   }
   return false;
@@ -225,6 +225,7 @@
         // an object allocated in the local block.
         if (MI->getOperand(i).isFI()) {
           int FrameIdx = MI->getOperand(i).getIndex();
+
           // Don't try this with values not in the local block.
           if (!MFI->isObjectPreAllocated(FrameIdx))
             continue;
@@ -232,13 +233,15 @@
           DEBUG(dbgs() << "Considering: " << *MI);
           if (TRI->needsFrameBaseReg(MI, i)) {
             unsigned BaseReg = 0;
-            unsigned Offset = 0;
+            int64_t Offset = 0;
 
             DEBUG(dbgs() << "  Replacing FI in: " << *MI);
 
             // If we have a suitable base register available, use it; otherwise
-            // create a new one.
-
+            // create a new one. Note that any offset encoded in the
+            // instruction itself will be taken into account by the target,
+            // so we don't have to adjust for it here when reusing a base
+            // register.
             std::pair<unsigned, int64_t> RegOffset;
             if (lookupCandidateBaseReg(BaseRegisters, RegOffset,
                                        LocalOffsets[FrameIdx], MI, TRI)) {
@@ -250,15 +253,26 @@
             } else {
               // No previously defined register was in range, so create a
               // new one.
+              int64_t InstrOffset = TRI->getFrameIndexInstrOffset(MI, i);
               const TargetRegisterClass *RC = TRI->getPointerRegClass();
               BaseReg = Fn.getRegInfo().createVirtualRegister(RC);
 
+              DEBUG(dbgs() << "  Materializing base register " << BaseReg <<
+                    " at frame local offset " <<
+                    LocalOffsets[FrameIdx] + InstrOffset << "\n");
               // Tell the target to insert the instruction to initialize
               // the base register.
-              TRI->materializeFrameBaseRegister(I, BaseReg, FrameIdx);
+              TRI->materializeFrameBaseRegister(I, BaseReg, FrameIdx,
+                                                InstrOffset);
 
-              BaseRegisters.push_back(std::pair<unsigned, int64_t>(BaseReg,
-                                                                   Offset));
+              // The base register already includes any offset specified
+              // by the instruction, so account for that so it doesn't get
+              // applied twice.
+              Offset = -InstrOffset;
+
+              BaseRegisters.push_back(
+                std::pair<unsigned, int64_t>(BaseReg,
+                                      LocalOffsets[FrameIdx] + InstrOffset));
               ++NumBaseRegisters;
             }
             assert(BaseReg != 0 && "Unable to allocate virtual base register!");

Modified: llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.cpp?rev=111585&r1=111584&r2=111585&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.cpp Thu Aug 19 18:52:25 2010
@@ -1367,6 +1367,59 @@
   MBB.erase(I);
 }
 
+
+int64_t ARMBaseRegisterInfo::
+getFrameIndexInstrOffset(MachineInstr *MI, int Idx) const {
+  const TargetInstrDesc &Desc = MI->getDesc();
+  unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask);
+  int64_t InstrOffs = 0;;
+  int Scale = 1;
+  unsigned ImmIdx = 0;
+  switch(AddrMode) {
+  case ARMII::AddrModeT2_i8:
+  case ARMII::AddrModeT2_i12:
+    // i8 supports only negative, and i12 supports only positive, so
+    // based on Offset sign, consider the appropriate instruction
+    InstrOffs = MI->getOperand(Idx+1).getImm();
+    Scale = 1;
+    break;
+  case ARMII::AddrMode5: {
+    // VFP address mode.
+    const MachineOperand &OffOp = MI->getOperand(Idx+1);
+    int InstrOffs = ARM_AM::getAM5Offset(OffOp.getImm());
+    if (ARM_AM::getAM5Op(OffOp.getImm()) == ARM_AM::sub)
+      InstrOffs = -InstrOffs;
+    Scale = 4;
+    break;
+  }
+  case ARMII::AddrMode2: {
+    ImmIdx = Idx+2;
+    InstrOffs = ARM_AM::getAM2Offset(MI->getOperand(ImmIdx).getImm());
+    if (ARM_AM::getAM2Op(MI->getOperand(ImmIdx).getImm()) == ARM_AM::sub)
+      InstrOffs = -InstrOffs;
+    break;
+  }
+  case ARMII::AddrMode3: {
+    ImmIdx = Idx+2;
+    InstrOffs = ARM_AM::getAM3Offset(MI->getOperand(ImmIdx).getImm());
+    if (ARM_AM::getAM3Op(MI->getOperand(ImmIdx).getImm()) == ARM_AM::sub)
+      InstrOffs = -InstrOffs;
+    break;
+  }
+  case ARMII::AddrModeT1_s: {
+    ImmIdx = Idx+1;
+    InstrOffs = MI->getOperand(ImmIdx).getImm();
+    Scale = 4;
+    break;
+  }
+  default:
+    llvm_unreachable("Unsupported addressing mode!");
+    break;
+  }
+
+  return InstrOffs * Scale;
+}
+
 /// needsFrameBaseReg - Returns true if the instruction's frame index
 /// reference would be better served by a base register other than FP
 /// or SP. Used by LocalStackFrameAllocation to determine which frame index
@@ -1404,8 +1457,8 @@
 /// materializeFrameBaseRegister - Insert defining instruction(s) for
 /// BaseReg to be a pointer to FrameIdx before insertion point I.
 void ARMBaseRegisterInfo::
-materializeFrameBaseRegister(MachineBasicBlock::iterator I,
-                             unsigned BaseReg, int FrameIdx) const {
+materializeFrameBaseRegister(MachineBasicBlock::iterator I, unsigned BaseReg,
+                             int FrameIdx, int64_t Offset) const {
   ARMFunctionInfo *AFI =
     I->getParent()->getParent()->getInfo<ARMFunctionInfo>();
   unsigned ADDriOpc = !AFI->isThumbFunction() ? ARM::ADDri :
@@ -1413,7 +1466,7 @@
 
   MachineInstrBuilder MIB =
     BuildMI(*I->getParent(), I, I->getDebugLoc(), TII.get(ADDriOpc), BaseReg)
-    .addFrameIndex(FrameIdx).addImm(0);
+    .addFrameIndex(FrameIdx).addImm(Offset);
   if (!AFI->isThumb1OnlyFunction())
     AddDefaultCC(AddDefaultPred(MIB));
 }
@@ -1445,8 +1498,8 @@
   assert (Done && "Unable to resolve frame index!");
 }
 
-bool ARMBaseRegisterInfo::isBaseRegInRange(const MachineInstr *MI,
-                                           unsigned Reg, int64_t Offset) const {
+bool ARMBaseRegisterInfo::isFrameOffsetLegal(const MachineInstr *MI,
+                                             int64_t Offset) const {
   const TargetInstrDesc &Desc = MI->getDesc();
   unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask);
   unsigned i = 0;
@@ -1464,6 +1517,7 @@
   unsigned Scale = 1;
   unsigned ImmIdx = 0;
   int InstrOffs = 0;;
+  bool isSigned = true;
   switch(AddrMode) {
   case ARMII::AddrModeT2_i8:
   case ARMII::AddrModeT2_i12:
@@ -1509,6 +1563,7 @@
     InstrOffs = MI->getOperand(ImmIdx).getImm();
     NumBits = 5;
     Scale = 4;
+    isSigned = false;
     break;
   }
   default:
@@ -1518,7 +1573,7 @@
 
   Offset += InstrOffs * Scale;
   assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!");
-  if (Offset < 0)
+  if (isSigned && Offset < 0)
     Offset = -Offset;
 
   unsigned Mask = (1 << NumBits) - 1;

Modified: llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.h?rev=111585&r1=111584&r2=111585&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.h (original)
+++ llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.h Thu Aug 19 18:52:25 2010
@@ -105,13 +105,14 @@
 
   bool canRealignStack(const MachineFunction &MF) const;
   bool needsStackRealignment(const MachineFunction &MF) const;
+  int64_t getFrameIndexInstrOffset(MachineInstr *MI, int Idx) const;
   bool needsFrameBaseReg(MachineInstr *MI, unsigned operand) const;
   void materializeFrameBaseRegister(MachineBasicBlock::iterator I,
-                                    unsigned BaseReg, int FrameIdx) const;
+                                    unsigned BaseReg, int FrameIdx,
+                                    int64_t Offset) const;
   void resolveFrameIndex(MachineBasicBlock::iterator I,
                          unsigned BaseReg, int64_t Offset) const;
-  bool isBaseRegInRange(const MachineInstr *MI, unsigned Reg,
-                        int64_t Offset) const;
+  bool isFrameOffsetLegal(const MachineInstr *MI, int64_t Offset) const;
 
   bool cannotEliminateFrame(const MachineFunction &MF) const;
 





More information about the llvm-commits mailing list