[llvm] r186831 - This adds range checking for "ldr Rn, [pc, #imm]" Thumb

Mihai Popa mihail.popa at gmail.com
Mon Jul 22 08:49:36 PDT 2013


Author: mpopa
Date: Mon Jul 22 10:49:36 2013
New Revision: 186831

URL: http://llvm.org/viewvc/llvm-project?rev=186831&view=rev
Log:
This adds range checking for "ldr Rn, [pc, #imm]" Thumb 
instructions. With this patch:

1. ldr.n is recognized as mnemonic for the short encoding
2. ldr.w is recognized as menmonic for the long encoding
3. ldr will map to either short or long encodings depending on the size of the offset

Modified:
    llvm/trunk/lib/Target/ARM/ARMInstrThumb.td
    llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td
    llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
    llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
    llvm/trunk/test/CodeGen/ARM/fast-isel-pic.ll
    llvm/trunk/test/CodeGen/ARM/indirectbr.ll
    llvm/trunk/test/CodeGen/ARM/load-global.ll
    llvm/trunk/test/CodeGen/ARM/machine-licm.ll
    llvm/trunk/test/CodeGen/Thumb/large-stack.ll
    llvm/trunk/test/MC/ARM/basic-thumb2-instructions.s

Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrThumb.td?rev=186831&r1=186830&r2=186831&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMInstrThumb.td (original)
+++ llvm/trunk/lib/Target/ARM/ARMInstrThumb.td Mon Jul 22 10:49:36 2013
@@ -100,6 +100,13 @@ class OperandUnsignedOffset_b8s2 : AsmOp
 
 def UnsignedOffset_b8s2 : OperandUnsignedOffset_b8s2;
 
+// thumb style PC relative operand. signed, 8 bits magnitude,
+// two bits shift. can be represented as either [pc, #imm], #imm,
+// or relocatable expression...
+def ThumbMemPC : AsmOperandClass {
+  let Name = "ThumbMemPC";
+}
+
 let OperandType = "OPERAND_PCREL" in {
 def t_brtarget : Operand<OtherVT> {
   let EncoderMethod = "getThumbBRTargetOpValue";
@@ -132,6 +139,15 @@ def t_blxtarget : Operand<i32> {
   let EncoderMethod = "getThumbBLXTargetOpValue";
   let DecoderMethod = "DecodeThumbBLXOffset";
 }
+
+// t_addrmode_pc := <label> => pc + imm8 * 4
+//
+def t_addrmode_pc : Operand<i32> {
+  let EncoderMethod = "getAddrModePCOpValue";
+  let DecoderMethod = "DecodeThumbAddrModePC";
+  let PrintMethod = "printThumbLdrLabelOperand";
+  let ParserMatchClass = ThumbMemPC;
+}
 }
 
 // t_addrmode_rr := reg + reg
@@ -228,14 +244,6 @@ def t_addrmode_sp : Operand<i32>,
   let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
 }
 
-// t_addrmode_pc := <label> => pc + imm8 * 4
-//
-def t_addrmode_pc : Operand<i32> {
-  let EncoderMethod = "getAddrModePCOpValue";
-  let DecoderMethod = "DecodeThumbAddrModePC";
-  let PrintMethod = "printThumbLdrLabelOperand";
-}
-
 //===----------------------------------------------------------------------===//
 //  Miscellaneous Instructions.
 //
@@ -640,11 +648,9 @@ def tLDRspi : T1pIs<(outs tGPR:$Rt), (in
   let Inst{7-0} = addr;
 }
 
-// Load tconstpool
-// FIXME: Use ldr.n to work around a darwin assembler bug.
-let canFoldAsLoad = 1, isReMaterializable = 1, isCodeGenOnly = 1 in
+let canFoldAsLoad = 1, isReMaterializable = 1 in
 def tLDRpci : T1pIs<(outs tGPR:$Rt), (ins t_addrmode_pc:$addr), IIC_iLoad_i,
-                  "ldr", ".n\t$Rt, $addr",
+                  "ldr", "\t$Rt, $addr",
                   [(set tGPR:$Rt, (load (ARMWrapper tconstpool:$addr)))]>,
               T1Encoding<{0,1,0,0,1,?}> {
   // A6.2 & A8.6.59
@@ -654,17 +660,8 @@ def tLDRpci : T1pIs<(outs tGPR:$Rt), (in
   let Inst{7-0}  = addr;
 }
 
-// FIXME: Remove this entry when the above ldr.n workaround is fixed.
-// For assembly/disassembly use only.
-def tLDRpciASM : T1pIs<(outs tGPR:$Rt), (ins t_addrmode_pc:$addr), IIC_iLoad_i,
-                       "ldr", "\t$Rt, $addr", []>,
-                 T1Encoding<{0,1,0,0,1,?}> {
-  // A6.2 & A8.6.59
-  bits<3> Rt;
-  bits<8> addr;
-  let Inst{10-8} = Rt;
-  let Inst{7-0}  = addr;
-}
+def : tInstAlias<"ldr${p}.n $Rt, $addr", 
+                 (tLDRpci tGPR:$Rt, t_addrmode_pc:$addr, pred:$p), 0>;
 
 // A8.6.194 & A8.6.192
 defm tSTR  : thumb_st_rr_ri_enc<0b000, 0b0110, t_addrmode_rrs4,

Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td?rev=186831&r1=186830&r2=186831&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td (original)
+++ llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td Mon Jul 22 10:49:36 2013
@@ -4399,7 +4399,7 @@ def t2LDRSHpcrel  : t2AsmPseudo<"ldrsh${
                          (ins GPRnopc:$Rt, t2ldr_pcrel_imm12:$addr, pred:$p)>;
     // Version w/ the .w suffix.
 def : t2InstAlias<"ldr${p}.w $Rt, $addr",
-                  (t2LDRpcrel GPRnopc:$Rt, t2ldr_pcrel_imm12:$addr, pred:$p)>;
+                  (t2LDRpcrel GPRnopc:$Rt, t2ldr_pcrel_imm12:$addr, pred:$p), 0>;
 def : t2InstAlias<"ldrb${p}.w $Rt, $addr",
                   (t2LDRBpcrel GPRnopc:$Rt, t2ldr_pcrel_imm12:$addr, pred:$p)>;
 def : t2InstAlias<"ldrh${p}.w $Rt, $addr",

Modified: llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp?rev=186831&r1=186830&r2=186831&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp (original)
+++ llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp Mon Jul 22 10:49:36 2013
@@ -609,6 +609,26 @@ public:
     }
     return false;
   }
+  // checks whether this operand is a memory operand computed as an offset
+  // applied to PC. the offset may have 8 bits of magnitude and is represented
+  // with two bits of shift. textually it may be either [pc, #imm], #imm or 
+  // relocable expression...
+  bool isThumbMemPC() const {
+    int64_t Val = 0;
+    if (isImm()) {
+      if (isa<MCSymbolRefExpr>(Imm.Val)) return true;
+      const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val);
+      if (!CE) return false;
+      Val = CE->getValue();
+    }
+    else if (isMem()) {
+      if(!Memory.OffsetImm || Memory.OffsetRegNum) return false;
+      if(Memory.BaseRegNum != ARM::PC) return false;
+      Val = Memory.OffsetImm->getValue();
+    }
+    else return false;
+    return ((Val % 4) == 0) && (Val >= -1020) && (Val <= 1020);
+  }
   bool isFPImm() const {
     if (!isImm()) return false;
     const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
@@ -1698,6 +1718,26 @@ public:
     Inst.addOperand(MCOperand::CreateExpr(SR));
   }
 
+  void addThumbMemPCOperands(MCInst &Inst, unsigned N) const {
+    assert(N == 1 && "Invalid number of operands!");
+    if (isImm()) {
+      const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+      if (CE) {
+        Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
+        return;
+      }
+
+      const MCSymbolRefExpr *SR = dyn_cast<MCSymbolRefExpr>(Imm.Val);
+      assert(SR && "Unknown value type!");
+      Inst.addOperand(MCOperand::CreateExpr(SR));
+      return;
+    }
+
+    assert(isMem()  && "Unknown value type!");
+    assert(isa<MCConstantExpr>(Memory.OffsetImm) && "Unknown value type!");
+    Inst.addOperand(MCOperand::CreateImm(Memory.OffsetImm->getValue()));
+  }
+
   void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
     assert(N == 1 && "Invalid number of operands!");
     // The operand is actually a so_imm, but we have its bitwise

Modified: llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp?rev=186831&r1=186830&r2=186831&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp (original)
+++ llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp Mon Jul 22 10:49:36 2013
@@ -152,7 +152,7 @@ static unsigned getRelaxedOpcode(unsigne
   switch (Op) {
   default: return Op;
   case ARM::tBcc:       return ARM::t2Bcc;
-  case ARM::tLDRpciASM: return ARM::t2LDRpci;
+  case ARM::tLDRpci:    return ARM::t2LDRpci;
   case ARM::tADR:       return ARM::t2ADR;
   case ARM::tB:         return ARM::t2B;
   }

Modified: llvm/trunk/test/CodeGen/ARM/fast-isel-pic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/fast-isel-pic.ll?rev=186831&r1=186830&r2=186831&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/fast-isel-pic.ll (original)
+++ llvm/trunk/test/CodeGen/ARM/fast-isel-pic.ll Mon Jul 22 10:49:36 2013
@@ -13,8 +13,8 @@ entry:
 ; THUMB: movt [[reg0]],
 ; THUMB: add  [[reg0]], pc
 ; THUMB-ELF: LoadGV
-; THUMB-ELF: ldr.n r[[reg0:[0-9]+]],
-; THUMB-ELF: ldr.n r[[reg1:[0-9]+]],
+; THUMB-ELF: ldr r[[reg0:[0-9]+]],
+; THUMB-ELF: ldr r[[reg1:[0-9]+]],
 ; THUMB-ELF: ldr r[[reg0]], [r[[reg0]], r[[reg1]]]
 ; ARM: LoadGV
 ; ARM: ldr [[reg1:r[0-9]+]],
@@ -41,8 +41,8 @@ entry:
 ; THUMB: add  r[[reg3]], pc
 ; THUMB: ldr  r[[reg3]], [r[[reg3]]]
 ; THUMB-ELF: LoadIndirectSymbol
-; THUMB-ELF: ldr.n r[[reg3:[0-9]+]],
-; THUMB-ELF: ldr.n r[[reg4:[0-9]+]],
+; THUMB-ELF: ldr r[[reg3:[0-9]+]],
+; THUMB-ELF: ldr r[[reg4:[0-9]+]],
 ; THUMB-ELF: ldr r[[reg3]], [r[[reg3]], r[[reg4]]]
 ; ARM: LoadIndirectSymbol
 ; ARM: ldr [[reg4:r[0-9]+]],

Modified: llvm/trunk/test/CodeGen/ARM/indirectbr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/indirectbr.ll?rev=186831&r1=186830&r2=186831&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/indirectbr.ll (original)
+++ llvm/trunk/test/CodeGen/ARM/indirectbr.ll Mon Jul 22 10:49:36 2013
@@ -51,12 +51,12 @@ L1:
 ; ARM: ldr [[R1:r[0-9]+]], LCPI
 ; ARM: add [[R1b:r[0-9]+]], pc, [[R1]]
 ; ARM: str [[R1b]]
-; THUMB: ldr.n
+; THUMB: ldr
 ; THUMB: add
-; THUMB: ldr.n [[R2:r[0-9]+]], LCPI
+; THUMB: ldr [[R2:r[0-9]+]], LCPI
 ; THUMB: add [[R2]], pc
 ; THUMB: str [[R2]]
-; THUMB2: ldr.n [[R2:r[0-9]+]], LCPI
+; THUMB2: ldr [[R2:r[0-9]+]], LCPI
 ; THUMB2-NEXT: str{{(.w)?}} [[R2]]
   store i8* blockaddress(@foo, %L5), i8** @nextaddr, align 4
   ret i32 %res.3

Modified: llvm/trunk/test/CodeGen/ARM/load-global.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/load-global.ll?rev=186831&r1=186830&r2=186831&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/load-global.ll (original)
+++ llvm/trunk/test/CodeGen/ARM/load-global.ll Mon Jul 22 10:49:36 2013
@@ -26,7 +26,7 @@ define i32 @test1() {
 ; PIC: .long L_G$non_lazy_ptr-(LPC0_0+8)
 
 ; PIC_T: _test1
-; PIC_T: ldr.n r0, LCPI0_0
+; PIC_T: ldr r0, LCPI0_0
 ; PIC_T: add r0, pc
 ; PIC_T: ldr r0, [r0]
 ; PIC_T: ldr r0, [r0]

Modified: llvm/trunk/test/CodeGen/ARM/machine-licm.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/machine-licm.ll?rev=186831&r1=186830&r2=186831&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/machine-licm.ll (original)
+++ llvm/trunk/test/CodeGen/ARM/machine-licm.ll Mon Jul 22 10:49:36 2013
@@ -40,7 +40,7 @@ bb.nph:
 ; ARM: .section
 
 ; THUMB: BB#1
-; THUMB: ldr.n r2, LCPI0_0
+; THUMB: ldr r2, LCPI0_0
 ; THUMB: add r2, pc
 ; THUMB: ldr r{{[0-9]+}}, [r2]
 ; THUMB: LBB0_2

Modified: llvm/trunk/test/CodeGen/Thumb/large-stack.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Thumb/large-stack.ll?rev=186831&r1=186830&r2=186831&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/Thumb/large-stack.ll (original)
+++ llvm/trunk/test/CodeGen/Thumb/large-stack.ll Mon Jul 22 10:49:36 2013
@@ -10,7 +10,7 @@ define void @test1() {
 
 define void @test2() {
 ; CHECK-LABEL: test2:
-; CHECK: ldr.n r0, LCPI
+; CHECK: ldr r0, LCPI
 ; CHECK: add sp, r0
 ; CHECK: subs r4, r7, #4
 ; CHECK: mov sp, r4
@@ -20,9 +20,9 @@ define void @test2() {
 
 define i32 @test3() {
 ; CHECK-LABEL: test3:
-; CHECK: ldr.n r1, LCPI
+; CHECK: ldr r1, LCPI
 ; CHECK: add sp, r1
-; CHECK: ldr.n r1, LCPI
+; CHECK: ldr r1, LCPI
 ; CHECK: add r1, sp
 ; CHECK: subs r4, r7, #4
 ; CHECK: mov sp, r4

Modified: llvm/trunk/test/MC/ARM/basic-thumb2-instructions.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/basic-thumb2-instructions.s?rev=186831&r1=186830&r2=186831&view=diff
==============================================================================
--- llvm/trunk/test/MC/ARM/basic-thumb2-instructions.s (original)
+++ llvm/trunk/test/MC/ARM/basic-thumb2-instructions.s Mon Jul 22 10:49:36 2013
@@ -772,6 +772,23 @@ _func:
 @ CHECK: ldr.w	lr, _strcmp-4           @ encoding: [0x5f'A',0xf8'A',A,0xe0'A']
 @ CHECK: @   fixup A - offset: 0, value: _strcmp-4, kind: fixup_t2_ldst_pcrel_12
 
+        ldr r4, [pc, #1020]
+        ldr r3, [pc, #-1020]
+        ldr r6, [pc, #1024]
+        ldr r0, [pc, #-1024]
+        ldr r2, [pc, #4095]
+        ldr r1, [pc, #-4095]
+        ldr.n r8, [pc, #132]
+        ldr.w r8, [pc, #132]
+
+@ CHECK: ldr	r4, [pc, #1020]       @ encoding: [0xff,0x4c]
+@ CHECK: ldr	r3, [pc, #-1020]      @ encoding: [0x01,0x4b]
+@ CHECK: ldr.w	r6, [pc, #1024]       @ encoding: [0xdf,0xf8,0x00,0x64]
+@ CHECK: ldr.w	r0, [pc, #-1024]      @ encoding: [0x5f,0xf8,0x00,0x04]
+@ CHECK: ldr.w	r2, [pc, #4095]       @ encoding: [0xdf,0xf8,0xff,0x2f]
+@ CHECK: ldr.w	r1, [pc, #-4095]      @ encoding: [0x5f,0xf8,0xff,0x1f]
+@ CHECK: ldr	r8, [pc, #132]        @ encoding: [0x21,0x48]
+@ CHECK: ldr.w	r8, [pc, #132]        @ encoding: [0xdf,0xf8,0x84,0x80]
 
 @------------------------------------------------------------------------------
 @ LDR(register)
@@ -3569,5 +3586,5 @@ _func:
 @ CHECK: ldrsh.w r11, [pc, #-22]        @ encoding: [0x3f,0xf9,0x16,0xb0]
 
 @ rdar://12596361
-        ldr r1, [pc, #12]
-@ CHECK: ldr.n r1, [pc, #12]        @ encoding: [0x03,0x49]
+         ldr r1, [pc, #12]
+@ CHECK: ldr r1, [pc, #12]              @ encoding: [0x03,0x49]





More information about the llvm-commits mailing list