[llvm-commits] [llvm] r74420 - in /llvm/trunk: lib/Target/ARM/ARMAddressingModes.h lib/Target/ARM/ARMConstantIslandPass.cpp lib/Target/ARM/ARMISelDAGToDAG.cpp lib/Target/ARM/ARMInstrFormats.td lib/Target/ARM/ARMInstrInfo.h lib/Target/ARM/ARMInstrInfo.td lib/Target/ARM/ARMInstrThumb.td lib/Target/ARM/ARMInstrThumb2.td lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp lib/Target/ARM/README.txt lib/Target/ARM/ThumbRegisterInfo.cpp test/CodeGen/ARM/ldr.ll test/CodeGen/Thumb2/thumb2-ldr.ll

Evan Cheng evan.cheng at apple.com
Mon Jun 29 00:51:05 PDT 2009


Author: evancheng
Date: Mon Jun 29 02:51:04 2009
New Revision: 74420

URL: http://llvm.org/viewvc/llvm-project?rev=74420&view=rev
Log:
Implement Thumb2 ldr.

After much back and forth, I decided to deviate from ARM design and split LDR into 4 instructions (r + imm12, r + imm8, r + r << imm12, constantpool). The advantage of this is 1) it follows the latest ARM technical manual, and 2) makes it easier to reduce the width of the instruction later. The down side is this creates more inconsistency between the two sub-targets. We should split ARM LDR instruction in a similar fashion later. I've added a README entry for this.

Added:
    llvm/trunk/test/CodeGen/Thumb2/thumb2-ldr.ll
Modified:
    llvm/trunk/lib/Target/ARM/ARMAddressingModes.h
    llvm/trunk/lib/Target/ARM/ARMConstantIslandPass.cpp
    llvm/trunk/lib/Target/ARM/ARMISelDAGToDAG.cpp
    llvm/trunk/lib/Target/ARM/ARMInstrFormats.td
    llvm/trunk/lib/Target/ARM/ARMInstrInfo.h
    llvm/trunk/lib/Target/ARM/ARMInstrInfo.td
    llvm/trunk/lib/Target/ARM/ARMInstrThumb.td
    llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td
    llvm/trunk/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp
    llvm/trunk/lib/Target/ARM/README.txt
    llvm/trunk/lib/Target/ARM/ThumbRegisterInfo.cpp
    llvm/trunk/test/CodeGen/ARM/ldr.ll

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

==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMAddressingModes.h (original)
+++ llvm/trunk/lib/Target/ARM/ARMAddressingModes.h Mon Jun 29 02:51:04 2009
@@ -305,7 +305,7 @@
   ///     abcdefgh abcdefgh abcdefgh abcdefgh    control = 3
   /// Return -1 if none of the above apply.
   /// See ARM Reference Manual A6.3.2.
-  static inline int getT2SOImmValSplat (unsigned V) {
+  static inline int getT2SOImmValSplat(unsigned V) {
     unsigned u, Vs, Imm;
     // control = 0
     if ((V & 0xffffff00) == 0) 

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

==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMConstantIslandPass.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMConstantIslandPass.cpp Mon Jun 29 02:51:04 2009
@@ -447,21 +447,24 @@
             Bits = 8;
             Scale = 4;  // +-(offset_8*4)
             break;
-          case ARMII::AddrModeT1:
+          case ARMII::AddrModeT1_1:
             Bits = 5;  // +offset_5
             break;
-          case ARMII::AddrModeT2:
+          case ARMII::AddrModeT1_2:
             Bits = 5;
             Scale = 2;  // +(offset_5*2)
             break;
-          case ARMII::AddrModeT4:
+          case ARMII::AddrModeT1_4:
             Bits = 5;
             Scale = 4;  // +(offset_5*4)
             break;
-          case ARMII::AddrModeTs:
+          case ARMII::AddrModeT1_s:
             Bits = 8;
             Scale = 4;  // +(offset_8*4)
             break;
+          case ARMII::AddrModeT2_pc:
+            Bits = 12;  // +-offset_12
+            break;
           }
 
           // Remember that this is a user of a CP entry.

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

==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMISelDAGToDAG.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMISelDAGToDAG.cpp Mon Jun 29 02:51:04 2009
@@ -64,6 +64,8 @@
 
   SDNode *Select(SDValue Op);
   virtual void InstructionSelect();
+  bool SelectShifterOperandReg(SDValue Op, SDValue N, SDValue &A,
+                               SDValue &B, SDValue &C);
   bool SelectAddrMode2(SDValue Op, SDValue N, SDValue &Base,
                        SDValue &Offset, SDValue &Opc);
   bool SelectAddrMode2Offset(SDValue Op, SDValue N,
@@ -92,10 +94,15 @@
   bool SelectThumbAddrModeSP(SDValue Op, SDValue N, SDValue &Base,
                              SDValue &OffImm);
 
-  bool SelectShifterOperandReg(SDValue Op, SDValue N, SDValue &A,
-                               SDValue &B, SDValue &C);
   bool SelectT2ShifterOperandReg(SDValue Op, SDValue N,
                                  SDValue &BaseReg, SDValue &Opc);
+  bool SelectT2AddrModeImm12(SDValue Op, SDValue N, SDValue &Base,
+                             SDValue &OffImm);
+  bool SelectT2AddrModeImm8(SDValue Op, SDValue N, SDValue &Base,
+                            SDValue &OffImm);
+  bool SelectT2AddrModeSoReg(SDValue Op, SDValue N, SDValue &Base,
+                             SDValue &OffReg, SDValue &ShImm);
+
   
   // Include the pieces autogenerated from the target description.
 #include "ARMGenDAGISel.inc"
@@ -116,6 +123,30 @@
   CurDAG->RemoveDeadNodes();
 }
 
+bool ARMDAGToDAGISel::SelectShifterOperandReg(SDValue Op,
+                                              SDValue N,
+                                              SDValue &BaseReg,
+                                              SDValue &ShReg,
+                                              SDValue &Opc) {
+  ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N);
+
+  // Don't match base register only case. That is matched to a separate
+  // lower complexity pattern with explicit register operand.
+  if (ShOpcVal == ARM_AM::no_shift) return false;
+  
+  BaseReg = N.getOperand(0);
+  unsigned ShImmVal = 0;
+  if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
+    ShReg = CurDAG->getRegister(0, MVT::i32);
+    ShImmVal = RHS->getZExtValue() & 31;
+  } else {
+    ShReg = N.getOperand(1);
+  }
+  Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal),
+                                  MVT::i32);
+  return true;
+}
+
 bool ARMDAGToDAGISel::SelectAddrMode2(SDValue Op, SDValue N,
                                       SDValue &Base, SDValue &Offset,
                                       SDValue &Opc) {
@@ -519,30 +550,6 @@
   return false;
 }
 
-bool ARMDAGToDAGISel::SelectShifterOperandReg(SDValue Op,
-                                              SDValue N,
-                                              SDValue &BaseReg,
-                                              SDValue &ShReg,
-                                              SDValue &Opc) {
-  ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N);
-
-  // Don't match base register only case. That is matched to a separate
-  // lower complexity pattern with explicit register operand.
-  if (ShOpcVal == ARM_AM::no_shift) return false;
-  
-  BaseReg = N.getOperand(0);
-  unsigned ShImmVal = 0;
-  if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
-    ShReg = CurDAG->getRegister(0, MVT::i32);
-    ShImmVal = RHS->getZExtValue() & 31;
-  } else {
-    ShReg = N.getOperand(1);
-  }
-  Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal),
-                                  MVT::i32);
-  return true;
-}
-
 bool ARMDAGToDAGISel::SelectT2ShifterOperandReg(SDValue Op, SDValue N,
                                                 SDValue &BaseReg,
                                                 SDValue &Opc) {
@@ -563,6 +570,106 @@
   return false;
 }
 
+bool ARMDAGToDAGISel::SelectT2AddrModeImm12(SDValue Op, SDValue N,
+                                            SDValue &Base, SDValue &OffImm) {
+  // Match simple R + imm12 operands.
+  if (N.getOpcode() != ISD::ADD)
+    return false;
+
+  if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
+    int RHSC = (int)RHS->getZExtValue();
+    if (RHSC >= 0 && RHSC < 0x1000) { // 12 bits.
+      Base   = N.getOperand(0);
+      OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
+      return true;
+    }
+  }
+
+  return false;
+}
+
+bool ARMDAGToDAGISel::SelectT2AddrModeImm8(SDValue Op, SDValue N,
+                                           SDValue &Base, SDValue &OffImm) {
+  if (N.getOpcode() == ISD::ADD) {
+    if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
+      int RHSC = (int)RHS->getZExtValue();
+      if (RHSC < 0 && RHSC > -0x100) { // 8 bits.
+        Base   = N.getOperand(0);
+        OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32);
+        return true;
+      }
+    }
+  } else if (N.getOpcode() == ISD::SUB) {
+    if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
+      int RHSC = (int)RHS->getZExtValue();
+      if (RHSC >= 0 && RHSC < 0x100) { // 8 bits.
+        Base   = N.getOperand(0);
+        OffImm = CurDAG->getTargetConstant(-RHSC, MVT::i32);
+        return true;
+      }
+    }
+  }
+
+  return false;
+}
+
+bool ARMDAGToDAGISel::SelectT2AddrModeSoReg(SDValue Op, SDValue N,
+                                            SDValue &Base,
+                                            SDValue &OffReg, SDValue &ShImm) {
+  // Base only.
+  if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB) {
+    Base = N;
+    if (N.getOpcode() == ISD::FrameIndex) {
+      int FI = cast<FrameIndexSDNode>(N)->getIndex();
+      Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
+    } else if (N.getOpcode() == ARMISD::Wrapper) {
+      Base = N.getOperand(0);
+      if (Base.getOpcode() == ISD::TargetConstantPool)
+        return false;  // We want to select t2LDRpci instead.
+    }
+    OffReg = CurDAG->getRegister(0, MVT::i32);
+    ShImm  = CurDAG->getTargetConstant(0, MVT::i32);
+    return true;
+  }
+
+  // Look for (R + R) or (R + (R << [1,2,3])).
+  unsigned ShAmt = 0;
+  Base   = N.getOperand(0);
+  OffReg = N.getOperand(1);
+
+  // Swap if it is ((R << c) + R).
+  ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(OffReg);
+  if (ShOpcVal != ARM_AM::lsl) {
+    ShOpcVal = ARM_AM::getShiftOpcForNode(Base);
+    if (ShOpcVal == ARM_AM::lsl)
+      std::swap(Base, OffReg);
+  }  
+  
+  if (ShOpcVal == ARM_AM::lsl) {
+    // Check to see if the RHS of the shift is a constant, if not, we can't fold
+    // it.
+    if (ConstantSDNode *Sh = dyn_cast<ConstantSDNode>(OffReg.getOperand(1))) {
+      ShAmt = Sh->getZExtValue();
+      if (ShAmt >= 4) {
+        ShAmt = 0;
+        ShOpcVal = ARM_AM::no_shift;
+      } else
+        OffReg = OffReg.getOperand(0);
+    } else {
+      ShOpcVal = ARM_AM::no_shift;
+    }
+  } else if (SelectT2AddrModeImm12(Op, N, Base, ShImm) ||
+             SelectT2AddrModeImm8 (Op, N, Base, ShImm))
+    // Don't match if it's possible to match to one of the r +/- imm cases.
+    return false;
+  
+  ShImm = CurDAG->getTargetConstant(ShAmt, MVT::i32);
+
+  return true;
+}
+
+//===--------------------------------------------------------------------===//
+
 /// getAL - Returns a ARMCC::AL immediate node.
 static inline SDValue getAL(SelectionDAG *CurDAG) {
   return CurDAG->getTargetConstant((uint64_t)ARMCC::AL, MVT::i32);

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

==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMInstrFormats.td (original)
+++ llvm/trunk/lib/Target/ARM/ARMInstrFormats.td Mon Jun 29 02:51:04 2009
@@ -59,6 +59,47 @@
 class UnaryDP  { bit isUnaryDataProc = 1; }
 
 //===----------------------------------------------------------------------===//
+// ARM Instruction flags.  These need to match ARMInstrInfo.h.
+//
+
+// Addressing mode.
+class AddrMode<bits<4> val> {
+  bits<4> Value = val;
+}
+def AddrModeNone  : AddrMode<0>;
+def AddrMode1     : AddrMode<1>;
+def AddrMode2     : AddrMode<2>;
+def AddrMode3     : AddrMode<3>;
+def AddrMode4     : AddrMode<4>;
+def AddrMode5     : AddrMode<5>;
+def AddrModeT1_1  : AddrMode<6>;
+def AddrModeT1_2  : AddrMode<7>;
+def AddrModeT1_4  : AddrMode<8>;
+def AddrModeT1_s  : AddrMode<9>;
+def AddrModeT2_i12: AddrMode<10>;
+def AddrModeT2_i8 : AddrMode<11>;
+def AddrModeT2_so : AddrMode<12>;
+def AddrModeT2_pc  : AddrMode<13>;
+
+// Instruction size.
+class SizeFlagVal<bits<3> val> {
+  bits<3> Value = val;
+}
+def SizeInvalid  : SizeFlagVal<0>;  // Unset.
+def SizeSpecial  : SizeFlagVal<1>;  // Pseudo or special.
+def Size8Bytes   : SizeFlagVal<2>;
+def Size4Bytes   : SizeFlagVal<3>;
+def Size2Bytes   : SizeFlagVal<4>;
+
+// Load / store index mode.
+class IndexMode<bits<2> val> {
+  bits<2> Value = val;
+}
+def IndexModeNone : IndexMode<0>;
+def IndexModePre  : IndexMode<1>;
+def IndexModePost : IndexMode<2>;
+
+//===----------------------------------------------------------------------===//
 
 // ARM Instruction templates.
 //
@@ -706,7 +747,6 @@
 // Thumb Instruction Format Definitions.
 //
 
-
 // TI - Thumb instruction.
 
 class ThumbI<dag outs, dag ins, AddrMode am, SizeFlagVal sz,
@@ -721,18 +761,6 @@
 
 class TI<dag outs, dag ins, string asm, list<dag> pattern>
   : ThumbI<outs, ins, AddrModeNone, Size2Bytes, asm, "", pattern>;
-class TI1<dag outs, dag ins, string asm, list<dag> pattern>
-  : ThumbI<outs, ins, AddrModeT1, Size2Bytes, asm, "", pattern>;
-class TI2<dag outs, dag ins, string asm, list<dag> pattern>
-  : ThumbI<outs, ins, AddrModeT2, Size2Bytes, asm, "", pattern>;
-class TI4<dag outs, dag ins, string asm, list<dag> pattern>
-  : ThumbI<outs, ins, AddrModeT4, Size2Bytes, asm, "", pattern>;
-class TIs<dag outs, dag ins, string asm, list<dag> pattern>
-  : ThumbI<outs, ins, AddrModeTs, Size2Bytes, asm, "", pattern>;
-
-// Two-address instructions
-class TIt<dag outs, dag ins, string asm, list<dag> pattern>
-  : ThumbI<outs, ins, AddrModeNone, Size2Bytes, asm, "$lhs = $dst", pattern>;
 
 // BL, BLX(1) are translated by assembler into two instructions
 class TIx2<dag outs, dag ins, string asm, list<dag> pattern>
@@ -764,6 +792,14 @@
 
 class T1I<dag outs, dag ins, string asm, list<dag> pattern>
   : Thumb1I<outs, ins, AddrModeNone, Size2Bytes, asm, "", pattern>;
+class T1I1<dag outs, dag ins, string asm, list<dag> pattern>
+  : Thumb1I<outs, ins, AddrModeT1_1, Size2Bytes, asm, "", pattern>;
+class T1I2<dag outs, dag ins, string asm, list<dag> pattern>
+  : Thumb1I<outs, ins, AddrModeT1_2, Size2Bytes, asm, "", pattern>;
+class T1I4<dag outs, dag ins, string asm, list<dag> pattern>
+  : Thumb1I<outs, ins, AddrModeT1_4, Size2Bytes, asm, "", pattern>;
+class T1Is<dag outs, dag ins, string asm, list<dag> pattern>
+  : Thumb1I<outs, ins, AddrModeT1_s, Size2Bytes, asm, "", pattern>;
 
 // Two-address instructions
 class T1It<dag outs, dag ins, string asm, list<dag> pattern>
@@ -812,6 +848,14 @@
 
 class T2I<dag oops, dag iops, string opc, string asm, list<dag> pattern>
   : Thumb2I<oops, iops, AddrModeNone, Size4Bytes, opc, asm, "", pattern>;
+class T2Ii12<dag oops, dag iops, string opc, string asm, list<dag> pattern>
+  : Thumb2I<oops, iops, AddrModeT2_i12, Size4Bytes, opc, asm, "", pattern>;
+class T2Ii8<dag oops, dag iops, string opc, string asm, list<dag> pattern>
+  : Thumb2I<oops, iops, AddrModeT2_i8, Size4Bytes, opc, asm, "", pattern>;
+class T2Iso<dag oops, dag iops, string opc, string asm, list<dag> pattern>
+  : Thumb2I<oops, iops, AddrModeT2_so, Size4Bytes, opc, asm, "", pattern>;
+class T2Ipc<dag oops, dag iops, string opc, string asm, list<dag> pattern>
+  : Thumb2I<oops, iops, AddrModeT2_pc, Size4Bytes, opc, asm, "", pattern>;
 
 class T2sI<dag oops, dag iops, string opc, string asm, list<dag> pattern>
   : Thumb2sI<oops, iops, AddrModeNone, Size4Bytes, opc, asm, "", pattern>;

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

==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMInstrInfo.h (original)
+++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.h Mon Jun 29 02:51:04 2009
@@ -39,10 +39,14 @@
     AddrMode3     = 3,
     AddrMode4     = 4,
     AddrMode5     = 5,
-    AddrModeT1    = 6,
-    AddrModeT2    = 7,
-    AddrModeT4    = 8,
-    AddrModeTs    = 9,  // i8 * 4 for pc and sp relative data
+    AddrModeT1_1  = 6,
+    AddrModeT1_2  = 7,
+    AddrModeT1_4  = 8,
+    AddrModeT1_s  = 9,  // i8 * 4 for pc and sp relative data
+    AddrModeT2_i12= 10,
+    AddrModeT2_i8 = 11,
+    AddrModeT2_so = 12,
+    AddrModeT2_pc = 13, // +/- i12 for pc relative data
 
     // Size* - Flags to keep track of the size of an instruction.
     SizeShift     = 4,

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

==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMInstrInfo.td (original)
+++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Mon Jun 29 02:51:04 2009
@@ -309,43 +309,6 @@
 }
 
 //===----------------------------------------------------------------------===//
-// ARM Instruction flags.  These need to match ARMInstrInfo.h.
-//
-
-// Addressing mode.
-class AddrMode<bits<4> val> {
-  bits<4> Value = val;
-}
-def AddrModeNone : AddrMode<0>;
-def AddrMode1    : AddrMode<1>;
-def AddrMode2    : AddrMode<2>;
-def AddrMode3    : AddrMode<3>;
-def AddrMode4    : AddrMode<4>;
-def AddrMode5    : AddrMode<5>;
-def AddrModeT1   : AddrMode<6>;
-def AddrModeT2   : AddrMode<7>;
-def AddrModeT4   : AddrMode<8>;
-def AddrModeTs   : AddrMode<9>;
-
-// Instruction size.
-class SizeFlagVal<bits<3> val> {
-  bits<3> Value = val;
-}
-def SizeInvalid  : SizeFlagVal<0>;  // Unset.
-def SizeSpecial  : SizeFlagVal<1>;  // Pseudo or special.
-def Size8Bytes   : SizeFlagVal<2>;
-def Size4Bytes   : SizeFlagVal<3>;
-def Size2Bytes   : SizeFlagVal<4>;
-
-// Load / store index mode.
-class IndexMode<bits<2> val> {
-  bits<2> Value = val;
-}
-def IndexModeNone : IndexMode<0>;
-def IndexModePre  : IndexMode<1>;
-def IndexModePost : IndexMode<2>;
-
-//===----------------------------------------------------------------------===//
 
 include "ARMInstrFormats.td"
 

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

==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMInstrThumb.td (original)
+++ llvm/trunk/lib/Target/ARM/ARMInstrThumb.td Mon Jun 29 02:51:04 2009
@@ -211,68 +211,68 @@
 //
 
 let canFoldAsLoad = 1 in
-def tLDR : TI4<(outs tGPR:$dst), (ins t_addrmode_s4:$addr),
+def tLDR : T1I4<(outs tGPR:$dst), (ins t_addrmode_s4:$addr),
                "ldr $dst, $addr",
                [(set tGPR:$dst, (load t_addrmode_s4:$addr))]>;
 
-def tLDRB : TI1<(outs tGPR:$dst), (ins t_addrmode_s1:$addr),
+def tLDRB : T1I1<(outs tGPR:$dst), (ins t_addrmode_s1:$addr),
                 "ldrb $dst, $addr",
                 [(set tGPR:$dst, (zextloadi8 t_addrmode_s1:$addr))]>;
 
-def tLDRH : TI2<(outs tGPR:$dst), (ins t_addrmode_s2:$addr),
+def tLDRH : T1I2<(outs tGPR:$dst), (ins t_addrmode_s2:$addr),
                 "ldrh $dst, $addr",
                 [(set tGPR:$dst, (zextloadi16 t_addrmode_s2:$addr))]>;
 
-def tLDRSB : TI1<(outs tGPR:$dst), (ins t_addrmode_rr:$addr),
+def tLDRSB : T1I1<(outs tGPR:$dst), (ins t_addrmode_rr:$addr),
                  "ldrsb $dst, $addr",
                  [(set tGPR:$dst, (sextloadi8 t_addrmode_rr:$addr))]>;
 
-def tLDRSH : TI2<(outs tGPR:$dst), (ins t_addrmode_rr:$addr),
+def tLDRSH : T1I2<(outs tGPR:$dst), (ins t_addrmode_rr:$addr),
                  "ldrsh $dst, $addr",
                  [(set tGPR:$dst, (sextloadi16 t_addrmode_rr:$addr))]>;
 
 let canFoldAsLoad = 1 in
-def tLDRspi : TIs<(outs tGPR:$dst), (ins t_addrmode_sp:$addr),
+def tLDRspi : T1Is<(outs tGPR:$dst), (ins t_addrmode_sp:$addr),
                   "ldr $dst, $addr",
                   [(set tGPR:$dst, (load t_addrmode_sp:$addr))]>;
 
 // Special instruction for restore. It cannot clobber condition register
 // when it's expanded by eliminateCallFramePseudoInstr().
 let canFoldAsLoad = 1, mayLoad = 1 in
-def tRestore : TIs<(outs tGPR:$dst), (ins t_addrmode_sp:$addr),
+def tRestore : T1Is<(outs tGPR:$dst), (ins t_addrmode_sp:$addr),
                     "ldr $dst, $addr", []>;
 
 // Load tconstpool
 let canFoldAsLoad = 1 in
-def tLDRpci : TIs<(outs tGPR:$dst), (ins i32imm:$addr),
+def tLDRpci : T1Is<(outs tGPR:$dst), (ins i32imm:$addr),
                   "ldr $dst, $addr",
                   [(set tGPR:$dst, (load (ARMWrapper tconstpool:$addr)))]>;
 
 // Special LDR for loads from non-pc-relative constpools.
 let canFoldAsLoad = 1, mayLoad = 1, isReMaterializable = 1 in
-def tLDRcp  : TIs<(outs tGPR:$dst), (ins i32imm:$addr),
+def tLDRcp  : T1Is<(outs tGPR:$dst), (ins i32imm:$addr),
                   "ldr $dst, $addr", []>;
 
-def tSTR : TI4<(outs), (ins tGPR:$src, t_addrmode_s4:$addr),
+def tSTR : T1I4<(outs), (ins tGPR:$src, t_addrmode_s4:$addr),
                "str $src, $addr",
                [(store tGPR:$src, t_addrmode_s4:$addr)]>;
 
-def tSTRB : TI1<(outs), (ins tGPR:$src, t_addrmode_s1:$addr),
+def tSTRB : T1I1<(outs), (ins tGPR:$src, t_addrmode_s1:$addr),
                  "strb $src, $addr",
                  [(truncstorei8 tGPR:$src, t_addrmode_s1:$addr)]>;
 
-def tSTRH : TI2<(outs), (ins tGPR:$src, t_addrmode_s2:$addr),
+def tSTRH : T1I2<(outs), (ins tGPR:$src, t_addrmode_s2:$addr),
                  "strh $src, $addr",
                  [(truncstorei16 tGPR:$src, t_addrmode_s2:$addr)]>;
 
-def tSTRspi : TIs<(outs), (ins tGPR:$src, t_addrmode_sp:$addr),
+def tSTRspi : T1Is<(outs), (ins tGPR:$src, t_addrmode_sp:$addr),
                    "str $src, $addr",
                    [(store tGPR:$src, t_addrmode_sp:$addr)]>;
 
 let mayStore = 1 in {
 // Special instruction for spill. It cannot clobber condition register
 // when it's expanded by eliminateCallFramePseudoInstr().
-def tSpill : TIs<(outs), (ins tGPR:$src, t_addrmode_sp:$addr),
+def tSpill : T1Is<(outs), (ins tGPR:$src, t_addrmode_sp:$addr),
                   "str $src, $addr", []>;
 }
 

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

==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td (original)
+++ llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td Mon Jun 29 02:51:04 2009
@@ -127,6 +127,30 @@
   }], t2_hi16>;
 
 
+// Define Thumb2 specific addressing modes.
+
+// t2addrmode_imm12  := reg + imm12
+def t2addrmode_imm12 : Operand<i32>,
+                       ComplexPattern<i32, 2, "SelectT2AddrModeImm12", []> {
+  let PrintMethod = "printT2AddrModeImm12Operand";
+  let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
+}
+
+// t2addrmode_imm8  := reg - imm8
+def t2addrmode_imm8 : Operand<i32>,
+                      ComplexPattern<i32, 2, "SelectT2AddrModeImm8", []> {
+  let PrintMethod = "printT2AddrModeImm8Operand";
+  let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
+}
+
+// t2addrmode_so_reg  := reg + reg << imm2
+def t2addrmode_so_reg : Operand<i32>,
+                        ComplexPattern<i32, 3, "SelectT2AddrModeSoReg", []> {
+  let PrintMethod = "printT2AddrModeSoRegOperand";
+  let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm);
+}
+
+
 //===----------------------------------------------------------------------===//
 // Multiclass helpers...
 //
@@ -409,6 +433,26 @@
 //  Load / store Instructions.
 //
 
+// Load
+let canFoldAsLoad = 1 in {
+def t2LDRi12 : T2Ii12<(outs GPR:$dst), (ins t2addrmode_imm12:$addr),
+                      "ldr", " $dst, $addr",
+                      [(set GPR:$dst, (load t2addrmode_imm12:$addr))]>;
+
+def t2LDRi8 : T2Ii8<(outs GPR:$dst), (ins t2addrmode_imm8:$addr),
+                    "ldr", " $dst, $addr",
+                    [(set GPR:$dst, (load t2addrmode_imm8:$addr))]>;
+
+def t2LDRs : T2Iso<(outs GPR:$dst), (ins t2addrmode_so_reg:$addr),
+                   "ldr", " $dst, $addr",
+                   [(set GPR:$dst, (load t2addrmode_so_reg:$addr))]>;
+
+// Load tconstpool
+def t2LDRpci : T2Ipc<(outs GPR:$dst), (ins i32imm:$addr),
+                     "ldr", " $dst, $addr",
+                     [(set GPR:$dst, (load (ARMWrapper tconstpool:$addr)))]>;
+} // canFoldAsLoad
+
 //===----------------------------------------------------------------------===//
 //  Move Instructions.
 //

Modified: llvm/trunk/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp?rev=74420&r1=74419&r2=74420&view=diff

==============================================================================
--- llvm/trunk/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp (original)
+++ llvm/trunk/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp Mon Jun 29 02:51:04 2009
@@ -93,45 +93,48 @@
       return "ARM Assembly Printer";
     }
 
-    void printOperand(const MachineInstr *MI, int opNum,
+    void printOperand(const MachineInstr *MI, int OpNum,
                       const char *Modifier = 0);
-    void printSOImmOperand(const MachineInstr *MI, int opNum);
-    void printSOImm2PartOperand(const MachineInstr *MI, int opNum);
-    void printSORegOperand(const MachineInstr *MI, int opNum);
-    void printAddrMode2Operand(const MachineInstr *MI, int OpNo);
-    void printAddrMode2OffsetOperand(const MachineInstr *MI, int OpNo);
-    void printAddrMode3Operand(const MachineInstr *MI, int OpNo);
-    void printAddrMode3OffsetOperand(const MachineInstr *MI, int OpNo);
-    void printAddrMode4Operand(const MachineInstr *MI, int OpNo,
+    void printSOImmOperand(const MachineInstr *MI, int OpNum);
+    void printSOImm2PartOperand(const MachineInstr *MI, int OpNum);
+    void printSORegOperand(const MachineInstr *MI, int OpNum);
+    void printAddrMode2Operand(const MachineInstr *MI, int OpNum);
+    void printAddrMode2OffsetOperand(const MachineInstr *MI, int OpNum);
+    void printAddrMode3Operand(const MachineInstr *MI, int OpNum);
+    void printAddrMode3OffsetOperand(const MachineInstr *MI, int OpNum);
+    void printAddrMode4Operand(const MachineInstr *MI, int OpNum,
                                const char *Modifier = 0);
-    void printAddrMode5Operand(const MachineInstr *MI, int OpNo,
+    void printAddrMode5Operand(const MachineInstr *MI, int OpNum,
                                const char *Modifier = 0);
-    void printAddrModePCOperand(const MachineInstr *MI, int OpNo,
+    void printAddrModePCOperand(const MachineInstr *MI, int OpNum,
                                 const char *Modifier = 0);
-    void printBitfieldInvMaskImmOperand (const MachineInstr *MI, int OpNo);
+    void printBitfieldInvMaskImmOperand (const MachineInstr *MI, int OpNum);
 
-    void printThumbAddrModeRROperand(const MachineInstr *MI, int OpNo);
-    void printThumbAddrModeRI5Operand(const MachineInstr *MI, int OpNo,
+    void printThumbAddrModeRROperand(const MachineInstr *MI, int OpNum);
+    void printThumbAddrModeRI5Operand(const MachineInstr *MI, int OpNum,
                                       unsigned Scale);
-    void printThumbAddrModeS1Operand(const MachineInstr *MI, int OpNo);
-    void printThumbAddrModeS2Operand(const MachineInstr *MI, int OpNo);
-    void printThumbAddrModeS4Operand(const MachineInstr *MI, int OpNo);
-    void printThumbAddrModeSPOperand(const MachineInstr *MI, int OpNo);
+    void printThumbAddrModeS1Operand(const MachineInstr *MI, int OpNum);
+    void printThumbAddrModeS2Operand(const MachineInstr *MI, int OpNum);
+    void printThumbAddrModeS4Operand(const MachineInstr *MI, int OpNum);
+    void printThumbAddrModeSPOperand(const MachineInstr *MI, int OpNum);
 
-    void printT2SOImmOperand(const MachineInstr *MI, int opNum);
+    void printT2SOImmOperand(const MachineInstr *MI, int OpNum);
     void printT2SOOperand(const MachineInstr *MI, int OpNum);
-
-    void printPredicateOperand(const MachineInstr *MI, int opNum);
-    void printSBitModifierOperand(const MachineInstr *MI, int opNum);
-    void printPCLabel(const MachineInstr *MI, int opNum);
-    void printRegisterList(const MachineInstr *MI, int opNum);
-    void printCPInstOperand(const MachineInstr *MI, int opNum,
+    void printT2AddrModeImm12Operand(const MachineInstr *MI, int OpNum);
+    void printT2AddrModeImm8Operand(const MachineInstr *MI, int OpNum);
+    void printT2AddrModeSoRegOperand(const MachineInstr *MI, int OpNum);
+
+    void printPredicateOperand(const MachineInstr *MI, int OpNum);
+    void printSBitModifierOperand(const MachineInstr *MI, int OpNum);
+    void printPCLabel(const MachineInstr *MI, int OpNum);
+    void printRegisterList(const MachineInstr *MI, int OpNum);
+    void printCPInstOperand(const MachineInstr *MI, int OpNum,
                             const char *Modifier);
-    void printJTBlockOperand(const MachineInstr *MI, int opNum);
+    void printJTBlockOperand(const MachineInstr *MI, int OpNum);
 
-    virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
+    virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
                                  unsigned AsmVariant, const char *ExtraCode);
-    virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
+    virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
                                        unsigned AsmVariant,
                                        const char *ExtraCode);
 
@@ -282,9 +285,9 @@
   return false;
 }
 
-void ARMAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
+void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
                                  const char *Modifier) {
-  const MachineOperand &MO = MI->getOperand(opNum);
+  const MachineOperand &MO = MI->getOperand(OpNum);
   switch (MO.getType()) {
   case MachineOperand::MO_Register: {
     unsigned Reg = MO.getReg();
@@ -606,6 +609,8 @@
   O << "#" << lsb << ", #" << width;
 }
 
+//===--------------------------------------------------------------------===//
+
 void
 ARMAsmPrinter::printThumbAddrModeRROperand(const MachineInstr *MI, int Op) {
   const MachineOperand &MO1 = MI->getOperand(Op);
@@ -659,6 +664,8 @@
   O << "]";
 }
 
+//===--------------------------------------------------------------------===//
+
 /// printT2SOImmOperand - T2SOImm is:
 ///  1. a 4-bit splat control value and 8 bit immediate value
 ///  2. a 5-bit rotate amount and a non-zero 8-bit immediate value
@@ -694,47 +701,99 @@
   O << "#" << ARM_AM::getSORegOffset(MO2.getImm());
 }
 
+void ARMAsmPrinter::printT2AddrModeImm12Operand(const MachineInstr *MI,
+                                                int OpNum) {
+  const MachineOperand &MO1 = MI->getOperand(OpNum);
+  const MachineOperand &MO2 = MI->getOperand(OpNum+1);
+
+  O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
+
+  unsigned OffImm = MO2.getImm();
+  if (OffImm)  // Don't print +0.
+    O << ", #+" << OffImm;
+  O << "]";
+}
+
+void ARMAsmPrinter::printT2AddrModeImm8Operand(const MachineInstr *MI,
+                                               int OpNum) {
+  const MachineOperand &MO1 = MI->getOperand(OpNum);
+  const MachineOperand &MO2 = MI->getOperand(OpNum+1);
+
+  O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
+
+  int32_t OffImm = (int32_t)MO2.getImm();
+  // Don't print +0.
+  if (OffImm < 0)
+    O << ", #-" << -OffImm;
+  else if (OffImm > 0)
+    O << ", #+" << OffImm;
+  O << "]";
+}
+
+void ARMAsmPrinter::printT2AddrModeSoRegOperand(const MachineInstr *MI,
+                                                int OpNum) {
+  const MachineOperand &MO1 = MI->getOperand(OpNum);
+  const MachineOperand &MO2 = MI->getOperand(OpNum+1);
+  const MachineOperand &MO3 = MI->getOperand(OpNum+2);
+
+  O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
+
+  if (MO2.getReg()) {
+    O << ", +"
+      << TM.getRegisterInfo()->get(MO2.getReg()).AsmName;
 
-void ARMAsmPrinter::printPredicateOperand(const MachineInstr *MI, int opNum) {
-  ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(opNum).getImm();
+    unsigned ShAmt = MO3.getImm();
+    if (ShAmt) {
+      assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!");
+      O << ", lsl #" << ShAmt;
+    }
+  }
+  O << "]";
+}
+
+
+//===--------------------------------------------------------------------===//
+
+void ARMAsmPrinter::printPredicateOperand(const MachineInstr *MI, int OpNum) {
+  ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
   if (CC != ARMCC::AL)
     O << ARMCondCodeToString(CC);
 }
 
-void ARMAsmPrinter::printSBitModifierOperand(const MachineInstr *MI, int opNum){
-  unsigned Reg = MI->getOperand(opNum).getReg();
+void ARMAsmPrinter::printSBitModifierOperand(const MachineInstr *MI, int OpNum){
+  unsigned Reg = MI->getOperand(OpNum).getReg();
   if (Reg) {
     assert(Reg == ARM::CPSR && "Expect ARM CPSR register!");
     O << 's';
   }
 }
 
-void ARMAsmPrinter::printPCLabel(const MachineInstr *MI, int opNum) {
-  int Id = (int)MI->getOperand(opNum).getImm();
+void ARMAsmPrinter::printPCLabel(const MachineInstr *MI, int OpNum) {
+  int Id = (int)MI->getOperand(OpNum).getImm();
   O << TAI->getPrivateGlobalPrefix() << "PC" << Id;
 }
 
-void ARMAsmPrinter::printRegisterList(const MachineInstr *MI, int opNum) {
+void ARMAsmPrinter::printRegisterList(const MachineInstr *MI, int OpNum) {
   O << "{";
-  for (unsigned i = opNum, e = MI->getNumOperands(); i != e; ++i) {
+  for (unsigned i = OpNum, e = MI->getNumOperands(); i != e; ++i) {
     printOperand(MI, i);
     if (i != e-1) O << ", ";
   }
   O << "}";
 }
 
-void ARMAsmPrinter::printCPInstOperand(const MachineInstr *MI, int OpNo,
+void ARMAsmPrinter::printCPInstOperand(const MachineInstr *MI, int OpNum,
                                        const char *Modifier) {
   assert(Modifier && "This operand only works with a modifier!");
   // There are two aspects to a CONSTANTPOOL_ENTRY operand, the label and the
   // data itself.
   if (!strcmp(Modifier, "label")) {
-    unsigned ID = MI->getOperand(OpNo).getImm();
+    unsigned ID = MI->getOperand(OpNum).getImm();
     O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
       << '_' << ID << ":\n";
   } else {
     assert(!strcmp(Modifier, "cpentry") && "Unknown modifier for CPE");
-    unsigned CPI = MI->getOperand(OpNo).getIndex();
+    unsigned CPI = MI->getOperand(OpNum).getIndex();
 
     const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPI];
     
@@ -746,9 +805,9 @@
   }
 }
 
-void ARMAsmPrinter::printJTBlockOperand(const MachineInstr *MI, int OpNo) {
-  const MachineOperand &MO1 = MI->getOperand(OpNo);
-  const MachineOperand &MO2 = MI->getOperand(OpNo+1); // Unique Id
+void ARMAsmPrinter::printJTBlockOperand(const MachineInstr *MI, int OpNum) {
+  const MachineOperand &MO1 = MI->getOperand(OpNum);
+  const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id
   unsigned JTI = MO1.getIndex();
   O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
     << '_' << JTI << '_' << MO2.getImm() << ":\n";
@@ -787,7 +846,7 @@
 }
 
 
-bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
+bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
                                     unsigned AsmVariant, const char *ExtraCode){
   // Does this asm operand have a single letter operand modifier?
   if (ExtraCode && ExtraCode[0]) {
@@ -797,10 +856,10 @@
     default: return true;  // Unknown modifier.
     case 'a': // Don't print "#" before a global var name or constant.
     case 'c': // Don't print "$" before a global var name or constant.
-      printOperand(MI, OpNo, "no_hash");
+      printOperand(MI, OpNum, "no_hash");
       return false;
     case 'P': // Print a VFP double precision register.
-      printOperand(MI, OpNo);
+      printOperand(MI, OpNum);
       return false;
     case 'Q':
       if (TM.getTargetData()->isLittleEndian())
@@ -812,24 +871,24 @@
       // Fallthrough
     case 'H': // Write second word of DI / DF reference.  
       // Verify that this operand has two consecutive registers.
-      if (!MI->getOperand(OpNo).isReg() ||
-          OpNo+1 == MI->getNumOperands() ||
-          !MI->getOperand(OpNo+1).isReg())
+      if (!MI->getOperand(OpNum).isReg() ||
+          OpNum+1 == MI->getNumOperands() ||
+          !MI->getOperand(OpNum+1).isReg())
         return true;
-      ++OpNo;   // Return the high-part.
+      ++OpNum;   // Return the high-part.
     }
   }
   
-  printOperand(MI, OpNo);
+  printOperand(MI, OpNum);
   return false;
 }
 
 bool ARMAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
-                                          unsigned OpNo, unsigned AsmVariant,
+                                          unsigned OpNum, unsigned AsmVariant,
                                           const char *ExtraCode) {
   if (ExtraCode && ExtraCode[0])
     return true; // Unknown modifier.
-  printAddrMode2Operand(MI, OpNo);
+  printAddrMode2Operand(MI, OpNum);
   return false;
 }
 

Modified: llvm/trunk/lib/Target/ARM/README.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/README.txt?rev=74420&r1=74419&r2=74420&view=diff

==============================================================================
--- llvm/trunk/lib/Target/ARM/README.txt (original)
+++ llvm/trunk/lib/Target/ARM/README.txt Mon Jun 29 02:51:04 2009
@@ -530,3 +530,10 @@
 
 ARM::MOVCCr is commutable (by flipping the condition). But we need to implement
 ARMInstrInfo::commuteInstruction() to support it.
+
+//===---------------------------------------------------------------------===//
+
+Split out LDR (literal) from normal ARM LDR instruction. Also consider spliting
+LDR into imm12 and so_reg forms. This allows us to clean up some code. e.g.
+ARMLoadStoreOptimizer does not need to look at LDR (literal) and LDR (so_reg)
+while ARMConstantIslandPass only need to worry about LDR (literal).

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

==============================================================================
--- llvm/trunk/lib/Target/ARM/ThumbRegisterInfo.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ThumbRegisterInfo.cpp Mon Jun 29 02:51:04 2009
@@ -444,7 +444,7 @@
     unsigned NumBits = 0;
     unsigned Scale = 1;
     switch (AddrMode) {
-    case ARMII::AddrModeTs: {
+    case ARMII::AddrModeT1_s: {
       ImmIdx = i+1;
       InstrOffs = MI.getOperand(ImmIdx).getImm();
       NumBits = (FrameReg == ARM::SP) ? 8 : 5;
@@ -472,7 +472,7 @@
     }
 
     bool isThumSpillRestore = Opcode == ARM::tRestore || Opcode == ARM::tSpill;
-    if (AddrMode == ARMII::AddrModeTs) {
+    if (AddrMode == ARMII::AddrModeT1_s) {
       // Thumb tLDRspi, tSTRspi. These will change to instructions that use
       // a different base register.
       NumBits = 5;
@@ -480,7 +480,7 @@
     }
     // If this is a thumb spill / restore, we will be using a constpool load to
     // materialize the offset.
-    if (AddrMode == ARMII::AddrModeTs && isThumSpillRestore)
+    if (AddrMode == ARMII::AddrModeT1_s && isThumSpillRestore)
       ImmOp.ChangeToImmediate(0);
     else {
       // Otherwise, it didn't fit. Pull in what we can to simplify the immed.

Modified: llvm/trunk/test/CodeGen/ARM/ldr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/ldr.ll?rev=74420&r1=74419&r2=74420&view=diff

==============================================================================
--- llvm/trunk/test/CodeGen/ARM/ldr.ll (original)
+++ llvm/trunk/test/CodeGen/ARM/ldr.ll Mon Jun 29 02:51:04 2009
@@ -1,23 +1,59 @@
-; RUN: llvm-as < %s | llc -march=arm | \
-; RUN:   grep {ldr r0} | count 3
+; RUN: llvm-as < %s | llc -march=arm | grep {ldr r0} | count 7
+; RUN: llvm-as < %s | llc -march=arm | grep mov | grep 1
+; RUN: llvm-as < %s | llc -march=arm | not grep mvn
+; RUN: llvm-as < %s | llc -march=arm | grep ldr | grep lsl
+; RUN: llvm-as < %s | llc -march=arm | grep ldr | grep lsr
 
 define i32 @f1(i32* %v) {
 entry:
-        %tmp = load i32* %v             ; <i32> [#uses=1]
+        %tmp = load i32* %v
         ret i32 %tmp
 }
 
 define i32 @f2(i32* %v) {
 entry:
-        %tmp2 = getelementptr i32* %v, i32 1023         ; <i32*> [#uses=1]
-        %tmp = load i32* %tmp2          ; <i32> [#uses=1]
+        %tmp2 = getelementptr i32* %v, i32 1023
+        %tmp = load i32* %tmp2
         ret i32 %tmp
 }
 
 define i32 @f3(i32* %v) {
 entry:
-        %tmp2 = getelementptr i32* %v, i32 1024         ; <i32*> [#uses=1]
-        %tmp = load i32* %tmp2          ; <i32> [#uses=1]
+        %tmp2 = getelementptr i32* %v, i32 1024
+        %tmp = load i32* %tmp2
         ret i32 %tmp
 }
 
+define i32 @f4(i32 %base) {
+entry:
+        %tmp1 = sub i32 %base, 128
+        %tmp2 = inttoptr i32 %tmp1 to i32*
+        %tmp3 = load i32* %tmp2
+        ret i32 %tmp3
+}
+
+define i32 @f5(i32 %base, i32 %offset) {
+entry:
+        %tmp1 = add i32 %base, %offset
+        %tmp2 = inttoptr i32 %tmp1 to i32*
+        %tmp3 = load i32* %tmp2
+        ret i32 %tmp3
+}
+
+define i32 @f6(i32 %base, i32 %offset) {
+entry:
+        %tmp1 = shl i32 %offset, 2
+        %tmp2 = add i32 %base, %tmp1
+        %tmp3 = inttoptr i32 %tmp2 to i32*
+        %tmp4 = load i32* %tmp3
+        ret i32 %tmp4
+}
+
+define i32 @f7(i32 %base, i32 %offset) {
+entry:
+        %tmp1 = lshr i32 %offset, 2
+        %tmp2 = add i32 %base, %tmp1
+        %tmp3 = inttoptr i32 %tmp2 to i32*
+        %tmp4 = load i32* %tmp3
+        ret i32 %tmp4
+}

Added: llvm/trunk/test/CodeGen/Thumb2/thumb2-ldr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Thumb2/thumb2-ldr.ll?rev=74420&view=auto

==============================================================================
--- llvm/trunk/test/CodeGen/Thumb2/thumb2-ldr.ll (added)
+++ llvm/trunk/test/CodeGen/Thumb2/thumb2-ldr.ll Mon Jun 29 02:51:04 2009
@@ -0,0 +1,59 @@
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep {ldr r0} | count 7
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep mov | grep 1
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | not grep mvn
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep ldr | grep lsl
+; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep lsr | not grep ldr
+
+define i32 @f1(i32* %v) {
+entry:
+        %tmp = load i32* %v
+        ret i32 %tmp
+}
+
+define i32 @f2(i32* %v) {
+entry:
+        %tmp2 = getelementptr i32* %v, i32 1023
+        %tmp = load i32* %tmp2
+        ret i32 %tmp
+}
+
+define i32 @f3(i32* %v) {
+entry:
+        %tmp2 = getelementptr i32* %v, i32 1024
+        %tmp = load i32* %tmp2
+        ret i32 %tmp
+}
+
+define i32 @f4(i32 %base) {
+entry:
+        %tmp1 = sub i32 %base, 128
+        %tmp2 = inttoptr i32 %tmp1 to i32*
+        %tmp3 = load i32* %tmp2
+        ret i32 %tmp3
+}
+
+define i32 @f5(i32 %base, i32 %offset) {
+entry:
+        %tmp1 = add i32 %base, %offset
+        %tmp2 = inttoptr i32 %tmp1 to i32*
+        %tmp3 = load i32* %tmp2
+        ret i32 %tmp3
+}
+
+define i32 @f6(i32 %base, i32 %offset) {
+entry:
+        %tmp1 = shl i32 %offset, 2
+        %tmp2 = add i32 %base, %tmp1
+        %tmp3 = inttoptr i32 %tmp2 to i32*
+        %tmp4 = load i32* %tmp3
+        ret i32 %tmp4
+}
+
+define i32 @f7(i32 %base, i32 %offset) {
+entry:
+        %tmp1 = lshr i32 %offset, 2
+        %tmp2 = add i32 %base, %tmp1
+        %tmp3 = inttoptr i32 %tmp2 to i32*
+        %tmp4 = load i32* %tmp3
+        ret i32 %tmp4
+}





More information about the llvm-commits mailing list