[llvm-commits] [llvm] r76883 - in /llvm/trunk/lib/Target/ARM: ARMBaseInstrInfo.h ARMBaseRegisterInfo.cpp ARMBaseRegisterInfo.h ARMInstrInfo.cpp ARMInstrInfo.h ARMInstrThumb2.td Thumb1InstrInfo.cpp Thumb1InstrInfo.h Thumb2InstrInfo.cpp Thumb2InstrInfo.h

David Goodwin david_goodwin at apple.com
Thu Jul 23 10:06:47 PDT 2009


Author: david_goodwin
Date: Thu Jul 23 12:06:46 2009
New Revision: 76883

URL: http://llvm.org/viewvc/llvm-project?rev=76883&view=rev
Log:
Fix frame index elimination to correctly handle thumb-2 addressing modes that don't allow negative offsets. During frame elimination convert *i12 opcode to a *i8 when necessary due to a negative offset.

Modified:
    llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h
    llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.cpp
    llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.h
    llvm/trunk/lib/Target/ARM/ARMInstrInfo.cpp
    llvm/trunk/lib/Target/ARM/ARMInstrInfo.h
    llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td
    llvm/trunk/lib/Target/ARM/Thumb1InstrInfo.cpp
    llvm/trunk/lib/Target/ARM/Thumb1InstrInfo.h
    llvm/trunk/lib/Target/ARM/Thumb2InstrInfo.cpp
    llvm/trunk/lib/Target/ARM/Thumb2InstrInfo.h

Modified: llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h?rev=76883&r1=76882&r2=76883&view=diff

==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h (original)
+++ llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h Thu Jul 23 12:06:46 2009
@@ -215,6 +215,13 @@
   // Return the opcode that implements 'Op', or 0 if no opcode
   virtual unsigned getOpcode(ARMII::Op Op) const =0;
 
+  // If 'opcode' is an instruction with an unsigned offset that also
+  // has a version with a signed offset, return the opcode for the
+  // version with the signed offset. In 'NumBits' return the number of
+  // bits for the signed offset.
+  virtual unsigned unsignedOffsetOpcodeToSigned(unsigned opcode,
+                                                unsigned *NumBits) const = 0;
+
   // Return true if the block does not fall through.
   virtual bool BlockHasNoFallThrough(const MachineBasicBlock &MBB) const =0;
 

Modified: llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.cpp?rev=76883&r1=76882&r2=76883&view=diff

==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.cpp Thu Jul 23 12:06:46 2009
@@ -142,6 +142,11 @@
   return TII.getOpcode((ARMII::Op)Op);
 }
 
+unsigned ARMBaseRegisterInfo::
+unsignedOffsetOpcodeToSigned(unsigned opcode, unsigned *NumBits) const {
+  return TII.unsignedOffsetOpcodeToSigned(opcode, NumBits);
+}
+
 const unsigned*
 ARMBaseRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
   static const unsigned CalleeSavedRegs[] = {
@@ -1109,6 +1114,8 @@
     int InstrOffs = 0;
     unsigned NumBits = 0;
     unsigned Scale = 1;
+    bool encodedOffset = true;
+    bool HandlesNeg = true;
     switch (AddrMode) {
     case ARMII::AddrMode2: {
       ImmIdx = i+2;
@@ -1139,17 +1146,21 @@
       ImmIdx = i+1;
       InstrOffs = MI.getOperand(ImmIdx).getImm();
       NumBits = 12;
+      encodedOffset = false;
+      HandlesNeg = false;
       break;
     }
     case ARMII::AddrModeT2_i8: {
       ImmIdx = i+1;
       InstrOffs = MI.getOperand(ImmIdx).getImm();
       NumBits = 8;
+      encodedOffset = false;
       break;
     }
     case ARMII::AddrModeT2_so: {
       ImmIdx = i+2;
       InstrOffs = MI.getOperand(ImmIdx).getImm();
+      encodedOffset = false;
       break;
     }
     default:
@@ -1160,29 +1171,55 @@
     Offset += InstrOffs * Scale;
     assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!");
     if (Offset < 0) {
+      // For addrmodes that cannot handle negative offsets, convert to
+      // an opcode that can, or set NumBits == 0 to avoid folding
+      // address computation
+      if (!HandlesNeg) {
+        unsigned usop = unsignedOffsetOpcodeToSigned(Opcode, &NumBits);
+        if (usop != 0) {
+          MI.setDesc(TII.get(usop));
+          HandlesNeg = true;
+          Opcode = usop;
+        }
+        else {
+          NumBits = 0;
+        }
+      }
+
       Offset = -Offset;
       isSub = true;
     }
 
-    // Common case: small offset, fits into instruction.
-    MachineOperand &ImmOp = MI.getOperand(ImmIdx);
-    int ImmedOffset = Offset / Scale;
-    unsigned Mask = (1 << NumBits) - 1;
-    if ((unsigned)Offset <= Mask * Scale) {
-      // Replace the FrameIndex with sp
-      MI.getOperand(i).ChangeToRegister(FrameReg, false);
-      if (isSub)
-        ImmedOffset |= 1 << NumBits;
+    // Attempt to fold address comp. if opcode has offset bits
+    if (NumBits > 0) {
+      // Common case: small offset, fits into instruction.
+      MachineOperand &ImmOp = MI.getOperand(ImmIdx);
+      int ImmedOffset = Offset / Scale;
+      unsigned Mask = (1 << NumBits) - 1;
+      if ((unsigned)Offset <= Mask * Scale) {
+        // Replace the FrameIndex with sp
+        MI.getOperand(i).ChangeToRegister(FrameReg, false);
+        if (isSub) {
+          if (encodedOffset)
+            ImmedOffset |= 1 << NumBits;
+          else
+            ImmedOffset = -ImmedOffset;
+        }
+        ImmOp.ChangeToImmediate(ImmedOffset);
+        return;
+      }
+      
+      // Otherwise, it didn't fit. Pull in what we can to simplify the immed.
+      ImmedOffset = ImmedOffset & Mask;
+      if (isSub) {
+          if (encodedOffset)
+            ImmedOffset |= 1 << NumBits;
+          else
+            ImmedOffset = -ImmedOffset;
+      }
       ImmOp.ChangeToImmediate(ImmedOffset);
-      return;
+      Offset &= ~(Mask*Scale);
     }
-
-    // Otherwise, it didn't fit. Pull in what we can to simplify the immed.
-    ImmedOffset = ImmedOffset & Mask;
-    if (isSub)
-      ImmedOffset |= 1 << NumBits;
-    ImmOp.ChangeToImmediate(ImmedOffset);
-    Offset &= ~(Mask*Scale);
   }
 
   // If we get here, the immediate doesn't fit into the instruction.  We folded

Modified: llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.h?rev=76883&r1=76882&r2=76883&view=diff

==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.h (original)
+++ llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.h Thu Jul 23 12:06:46 2009
@@ -59,6 +59,13 @@
   // Return the opcode that implements 'Op', or 0 if no opcode
   unsigned getOpcode(int Op) const;
 
+  // If 'opcode' is an instruction with an unsigned offset that also
+  // has a version with a signed offset, return the opcode for the
+  // version with the signed offset. In 'NumBits' return the number of
+  // bits for the signed offset.
+  unsigned unsignedOffsetOpcodeToSigned(unsigned opcode,
+                                        unsigned *NumBits) const;
+
 public:
   /// getRegisterNumbering - Given the enum value for some register, e.g.
   /// ARM::LR, return the number that it corresponds to (e.g. 14). It

Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.cpp?rev=76883&r1=76882&r2=76883&view=diff

==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMInstrInfo.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.cpp Thu Jul 23 12:06:46 2009
@@ -30,6 +30,11 @@
 }
 
 unsigned ARMInstrInfo::
+unsignedOffsetOpcodeToSigned(unsigned opcode, unsigned *NumBits) const {
+  return 0;
+}
+
+unsigned ARMInstrInfo::
 getUnindexedOpcode(unsigned Opc) const {
   switch (Opc) {
   default: break;

Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.h?rev=76883&r1=76882&r2=76883&view=diff

==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMInstrInfo.h (original)
+++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.h Thu Jul 23 12:06:46 2009
@@ -35,6 +35,13 @@
   // Return the opcode that implements 'Op', or 0 if no opcode
   unsigned getOpcode(ARMII::Op Op) const;
 
+  // If 'opcode' is an instruction with an unsigned offset that also
+  // has a version with a signed offset, return the opcode for the
+  // version with the signed offset. In 'NumBits' return the number of
+  // bits for the signed offset.
+  unsigned unsignedOffsetOpcodeToSigned(unsigned opcode,
+                                        unsigned *NumBits) const;
+
   // Return true if the block does not fall through.
   bool BlockHasNoFallThrough(const MachineBasicBlock &MBB) const;
 

Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td?rev=76883&r1=76882&r2=76883&view=diff

==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td (original)
+++ llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td Thu Jul 23 12:06:46 2009
@@ -109,7 +109,7 @@
   let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
 }
 
-// t2addrmode_imm8  := reg - imm8
+// t2addrmode_imm8  := reg +/- imm8
 def t2addrmode_imm8 : Operand<i32>,
                       ComplexPattern<i32, 2, "SelectT2AddrModeImm8", []> {
   let PrintMethod = "printT2AddrModeImm8Operand";

Modified: llvm/trunk/lib/Target/ARM/Thumb1InstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Thumb1InstrInfo.cpp?rev=76883&r1=76882&r2=76883&view=diff

==============================================================================
--- llvm/trunk/lib/Target/ARM/Thumb1InstrInfo.cpp (original)
+++ llvm/trunk/lib/Target/ARM/Thumb1InstrInfo.cpp Thu Jul 23 12:06:46 2009
@@ -30,6 +30,12 @@
   return 0;
 }
 
+unsigned
+Thumb1InstrInfo::unsignedOffsetOpcodeToSigned(unsigned opcode,
+                                              unsigned *NumBits) const {
+  return 0;
+}
+
 unsigned Thumb1InstrInfo::getOpcode(ARMII::Op Op) const {
   switch (Op) {
   case ARMII::ADDri: return ARM::tADDi8;

Modified: llvm/trunk/lib/Target/ARM/Thumb1InstrInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Thumb1InstrInfo.h?rev=76883&r1=76882&r2=76883&view=diff

==============================================================================
--- llvm/trunk/lib/Target/ARM/Thumb1InstrInfo.h (original)
+++ llvm/trunk/lib/Target/ARM/Thumb1InstrInfo.h Thu Jul 23 12:06:46 2009
@@ -34,6 +34,13 @@
   // Return the opcode that implements 'Op', or 0 if no opcode
   unsigned getOpcode(ARMII::Op Op) const;
 
+  // If 'opcode' is an instruction with an unsigned offset that also
+  // has a version with a signed offset, return the opcode for the
+  // version with the signed offset. In 'NumBits' return the number of
+  // bits for the signed offset.
+  unsigned unsignedOffsetOpcodeToSigned(unsigned opcode,
+                                        unsigned *NumBits) const;
+
   // Return true if the block does not fall through.
   bool BlockHasNoFallThrough(const MachineBasicBlock &MBB) const;
 

Modified: llvm/trunk/lib/Target/ARM/Thumb2InstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Thumb2InstrInfo.cpp?rev=76883&r1=76882&r2=76883&view=diff

==============================================================================
--- llvm/trunk/lib/Target/ARM/Thumb2InstrInfo.cpp (original)
+++ llvm/trunk/lib/Target/ARM/Thumb2InstrInfo.cpp Thu Jul 23 12:06:46 2009
@@ -88,6 +88,29 @@
   return false;
 }
 
+unsigned
+Thumb2InstrInfo::unsignedOffsetOpcodeToSigned(unsigned opcode,
+                                              unsigned *NumBits) const
+{
+  if (NumBits != NULL)
+    *NumBits = 8;
+
+  switch (opcode) {
+  case ARM::t2LDRi12:   return ARM::t2LDRi8;
+  case ARM::t2LDRHi12:  return ARM::t2LDRHi8;
+  case ARM::t2LDRBi12:  return ARM::t2LDRBi8;
+  case ARM::t2LDRSHi12: return ARM::t2LDRSHi8;
+  case ARM::t2LDRSBi12: return ARM::t2LDRSBi8;
+  case ARM::t2STRi12:   return ARM::t2STRi8;
+  case ARM::t2STRBi12:  return ARM::t2STRBi8;
+  case ARM::t2STRHi12:  return ARM::t2STRHi8;
+  default:
+    break;
+  }
+
+  return 0;
+}
+
 bool
 Thumb2InstrInfo::copyRegToReg(MachineBasicBlock &MBB,
                               MachineBasicBlock::iterator I,

Modified: llvm/trunk/lib/Target/ARM/Thumb2InstrInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Thumb2InstrInfo.h?rev=76883&r1=76882&r2=76883&view=diff

==============================================================================
--- llvm/trunk/lib/Target/ARM/Thumb2InstrInfo.h (original)
+++ llvm/trunk/lib/Target/ARM/Thumb2InstrInfo.h Thu Jul 23 12:06:46 2009
@@ -34,6 +34,13 @@
   // Return the opcode that implements 'Op', or 0 if no opcode
   unsigned getOpcode(ARMII::Op Op) const;
 
+  // If 'opcode' is an instruction with an unsigned offset that also
+  // has a version with a signed offset, return the opcode for the
+  // version with the signed offset. In 'NumBits' return the number of
+  // bits for the signed offset.
+  unsigned unsignedOffsetOpcodeToSigned(unsigned opcode,
+                                        unsigned *NumBits) const;
+
   // Return true if the block does not fall through.
   bool BlockHasNoFallThrough(const MachineBasicBlock &MBB) const;
 





More information about the llvm-commits mailing list