[llvm] r278015 - [ARM] Add support for embedded position-independent code

Oliver Stannard via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 8 08:28:32 PDT 2016


Author: olista01
Date: Mon Aug  8 10:28:31 2016
New Revision: 278015

URL: http://llvm.org/viewvc/llvm-project?rev=278015&view=rev
Log:
[ARM] Add support for embedded position-independent code

This patch adds support for some new relocation models to the ARM
backend:

* Read-only position independence (ROPI): Code and read-only data is accessed
  PC-relative. The offsets between all code and RO data sections are known at
  static link time. This does not affect read-write data.
* Read-write position independence (RWPI): Read-write data is accessed relative
  to the static base register (r9). The offsets between all writeable data
  sections are known at static link time. This does not affect read-only data.

These two modes are independent (they specify how different objects
should be addressed), so they can be used individually or together. They
are otherwise the same as the "static" relocation model, and are not
compatible with SysV-style PIC using a global offset table.

These modes are normally used by bare-metal systems or systems with
small real-time operating systems. They are designed to avoid the need
for a dynamic linker, the only initialisation required is setting r9 to
an appropriate value for RWPI code.

I have only added support to SelectionDAG, not FastISel, because
FastISel is currently disabled for bare-metal targets where these modes
would be used.

Differential Revision: https://reviews.llvm.org/D23195


Added:
    llvm/trunk/test/CodeGen/ARM/arm-position-independence-jump-table.ll
    llvm/trunk/test/CodeGen/ARM/arm-position-independence.ll
Modified:
    llvm/trunk/include/llvm/CodeGen/CommandFlags.h
    llvm/trunk/include/llvm/Support/CodeGen.h
    llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp
    llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp
    llvm/trunk/lib/Target/ARM/ARMConstantPoolValue.cpp
    llvm/trunk/lib/Target/ARM/ARMConstantPoolValue.h
    llvm/trunk/lib/Target/ARM/ARMFastISel.cpp
    llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp
    llvm/trunk/lib/Target/ARM/ARMSubtarget.cpp
    llvm/trunk/lib/Target/ARM/ARMSubtarget.h
    llvm/trunk/lib/Target/ARM/ARMTargetMachine.cpp
    llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp
    llvm/trunk/lib/Target/TargetLoweringObjectFile.cpp
    llvm/trunk/test/CodeGen/ARM/build-attributes.ll

Modified: llvm/trunk/include/llvm/CodeGen/CommandFlags.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/CommandFlags.h?rev=278015&r1=278014&r2=278015&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/CommandFlags.h (original)
+++ llvm/trunk/include/llvm/CodeGen/CommandFlags.h Mon Aug  8 10:28:31 2016
@@ -54,6 +54,12 @@ cl::opt<Reloc::Model> RelocModel(
                    "Fully relocatable, position independent code"),
         clEnumValN(Reloc::DynamicNoPIC, "dynamic-no-pic",
                    "Relocatable external references, non-relocatable code"),
+        clEnumValN(Reloc::ROPI, "ropi",
+                   "Code and read-only data relocatable, accessed PC-relative"),
+        clEnumValN(Reloc::RWPI, "rwpi",
+                   "Read-write data relocatable, accessed relative to static base"),
+        clEnumValN(Reloc::ROPI_RWPI, "ropi-rwpi",
+                   "Combination of ropi and rwpi"),
         clEnumValEnd));
 
 static inline Optional<Reloc::Model> getRelocModel() {

Modified: llvm/trunk/include/llvm/Support/CodeGen.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/CodeGen.h?rev=278015&r1=278014&r2=278015&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/CodeGen.h (original)
+++ llvm/trunk/include/llvm/Support/CodeGen.h Mon Aug  8 10:28:31 2016
@@ -19,7 +19,7 @@ namespace llvm {
 
   // Relocation model types.
   namespace Reloc {
-  enum Model { Static, PIC_, DynamicNoPIC };
+  enum Model { Static, PIC_, DynamicNoPIC, ROPI, RWPI, ROPI_RWPI };
   }
 
   // Code model types.

Modified: llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp?rev=278015&r1=278014&r2=278015&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp Mon Aug  8 10:28:31 2016
@@ -725,16 +725,27 @@ void ARMAsmPrinter::emitAttributes() {
       ATS.emitFPU(ARM::FK_VFPV2);
   }
 
+  // RW data addressing.
   if (isPositionIndependent()) {
-    // PIC specific attributes.
     ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_RW_data,
                       ARMBuildAttrs::AddressRWPCRel);
+  } else if (STI.isRWPI()) {
+    // RWPI specific attributes.
+    ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_RW_data,
+                      ARMBuildAttrs::AddressRWSBRel);
+  }
+
+  // RO data addressing.
+  if (isPositionIndependent() || STI.isROPI()) {
     ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_RO_data,
                       ARMBuildAttrs::AddressROPCRel);
+  }
+
+  // GOT use.
+  if (isPositionIndependent()) {
     ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_GOT_use,
                       ARMBuildAttrs::AddressGOT);
   } else {
-    // Allow direct addressing of imported data for all other relocation models.
     ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_GOT_use,
                       ARMBuildAttrs::AddressDirect);
   }
@@ -858,14 +869,16 @@ void ARMAsmPrinter::emitAttributes() {
     }
   }
 
-  // TODO: We currently only support either reserving the register, or treating
-  // it as another callee-saved register, but not as SB or a TLS pointer; It
-  // would instead be nicer to push this from the frontend as metadata, as we do
-  // for the wchar and enum size tags
-  if (STI.isR9Reserved())
-    ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_R9_use, ARMBuildAttrs::R9Reserved);
+  // We currently do not support using R9 as the TLS pointer.
+  if (STI.isRWPI())
+    ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_R9_use,
+                      ARMBuildAttrs::R9IsSB);
+  else if (STI.isR9Reserved())
+    ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_R9_use,
+                      ARMBuildAttrs::R9Reserved);
   else
-    ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_R9_use, ARMBuildAttrs::R9IsGPR);
+    ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_R9_use,
+                      ARMBuildAttrs::R9IsGPR);
 
   if (STI.hasTrustZone() && STI.hasVirtualization())
     ATS.emitAttribute(ARMBuildAttrs::Virtualization_use,
@@ -899,6 +912,8 @@ getModifierVariantKind(ARMCP::ARMCPModif
     return MCSymbolRefExpr::VK_TPOFF;
   case ARMCP::GOTTPOFF:
     return MCSymbolRefExpr::VK_GOTTPOFF;
+  case ARMCP::SBREL:
+    return MCSymbolRefExpr::VK_ARM_SBREL;
   case ARMCP::GOT_PREL:
     return MCSymbolRefExpr::VK_ARM_GOT_PREL;
   case ARMCP::SECREL:
@@ -1037,7 +1052,7 @@ void ARMAsmPrinter::EmitJumpTableAddrs(c
     //    .word (LBB1 - LJTI_0_0)
     const MCExpr *Expr = MCSymbolRefExpr::create(MBB->getSymbol(), OutContext);
 
-    if (isPositionIndependent())
+    if (isPositionIndependent() || Subtarget->isROPI())
       Expr = MCBinaryExpr::createSub(Expr, MCSymbolRefExpr::create(JTISymbol,
                                                                    OutContext),
                                      OutContext);

Modified: llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp?rev=278015&r1=278014&r2=278015&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp Mon Aug  8 10:28:31 2016
@@ -4119,6 +4119,9 @@ bool ARMBaseInstrInfo::verifyInstruction
 void ARMBaseInstrInfo::expandLoadStackGuardBase(MachineBasicBlock::iterator MI,
                                                 unsigned LoadImmOpc,
                                                 unsigned LoadOpc) const {
+  assert(!Subtarget.isROPI() && !Subtarget.isRWPI() &&
+         "ROPI/RWPI not currently supported with stack guard");
+
   MachineBasicBlock &MBB = *MI->getParent();
   DebugLoc DL = MI->getDebugLoc();
   unsigned Reg = MI->getOperand(0).getReg();

Modified: llvm/trunk/lib/Target/ARM/ARMConstantPoolValue.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMConstantPoolValue.cpp?rev=278015&r1=278014&r2=278015&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMConstantPoolValue.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMConstantPoolValue.cpp Mon Aug  8 10:28:31 2016
@@ -60,6 +60,8 @@ const char *ARMConstantPoolValue::getMod
     return "gottpoff";
   case ARMCP::TPOFF:
     return "tpoff";
+  case ARMCP::SBREL:
+    return "SBREL";
   case ARMCP::SECREL:
     return "secrel32";
   }

Modified: llvm/trunk/lib/Target/ARM/ARMConstantPoolValue.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMConstantPoolValue.h?rev=278015&r1=278014&r2=278015&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMConstantPoolValue.h (original)
+++ llvm/trunk/lib/Target/ARM/ARMConstantPoolValue.h Mon Aug  8 10:28:31 2016
@@ -43,6 +43,7 @@ namespace ARMCP {
     GOTTPOFF,    /// Global Offset Table, Thread Pointer Offset
     TPOFF,       /// Thread Pointer Offset
     SECREL,      /// Section Relative (Windows TLS)
+    SBREL,       /// Static Base Relative (RWPI)
   };
 }
 

Modified: llvm/trunk/lib/Target/ARM/ARMFastISel.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMFastISel.cpp?rev=278015&r1=278014&r2=278015&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMFastISel.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMFastISel.cpp Mon Aug  8 10:28:31 2016
@@ -546,6 +546,10 @@ unsigned ARMFastISel::ARMMaterializeGV(c
   // For now 32-bit only.
   if (VT != MVT::i32 || GV->isThreadLocal()) return 0;
 
+  // ROPI/RWPI not currently supported.
+  if (Subtarget->isROPI() || Subtarget->isRWPI())
+    return 0;
+
   bool IsIndirect = Subtarget->isGVIndirectSymbol(GV);
   const TargetRegisterClass *RC = isThumb2 ? &ARM::rGPRRegClass
                                            : &ARM::GPRRegClass;

Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp?rev=278015&r1=278014&r2=278015&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp Mon Aug  8 10:28:31 2016
@@ -2530,7 +2530,7 @@ SDValue ARMTargetLowering::LowerBlockAdd
   EVT PtrVT = getPointerTy(DAG.getDataLayout());
   const BlockAddress *BA = cast<BlockAddressSDNode>(Op)->getBlockAddress();
   SDValue CPAddr;
-  bool IsPositionIndependent = isPositionIndependent();
+  bool IsPositionIndependent = isPositionIndependent() || Subtarget->isROPI();
   if (!IsPositionIndependent) {
     CPAddr = DAG.getTargetConstantPool(BA, PtrVT, 4);
   } else {
@@ -2800,6 +2800,11 @@ SDValue ARMTargetLowering::LowerGlobalAd
   SDLoc dl(Op);
   const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
   const TargetMachine &TM = getTargetMachine();
+  if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV))
+    GV = GA->getBaseObject();
+  bool IsRO =
+      (isa<GlobalVariable>(GV) && cast<GlobalVariable>(GV)->isConstant()) ||
+      isa<Function>(GV);
   if (isPositionIndependent()) {
     bool UseGOT_PREL = !TM.shouldAssumeDSOLocal(*GV->getParent(), GV);
 
@@ -2826,6 +2831,23 @@ SDValue ARMTargetLowering::LowerGlobalAd
           DAG.getLoad(PtrVT, dl, Chain, Result,
                       MachinePointerInfo::getGOT(DAG.getMachineFunction()));
     return Result;
+  } else if (Subtarget->isROPI() && IsRO) {
+    // PC-relative.
+    SDValue G = DAG.getTargetGlobalAddress(GV, dl, PtrVT);
+    SDValue Result = DAG.getNode(ARMISD::WrapperPIC, dl, PtrVT, G);
+    return Result;
+  } else if (Subtarget->isRWPI() && !IsRO) {
+    // SB-relative.
+    ARMConstantPoolValue *CPV =
+      ARMConstantPoolConstant::Create(GV, ARMCP::SBREL);
+    SDValue CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, 4);
+    CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
+    SDValue G = DAG.getLoad(
+        PtrVT, dl, DAG.getEntryNode(), CPAddr,
+        MachinePointerInfo::getConstantPool(DAG.getMachineFunction()));
+    SDValue SB = DAG.getCopyFromReg(DAG.getEntryNode(), dl, ARM::R9, PtrVT);
+    SDValue Result = DAG.getNode(ISD::ADD, dl, PtrVT, SB, G);
+    return Result;
   }
 
   // If we have T2 ops, we can materialize the address directly via movt/movw
@@ -2847,6 +2869,8 @@ SDValue ARMTargetLowering::LowerGlobalAd
 
 SDValue ARMTargetLowering::LowerGlobalAddressDarwin(SDValue Op,
                                                     SelectionDAG &DAG) const {
+  assert(!Subtarget->isROPI() && !Subtarget->isRWPI() &&
+         "ROPI/RWPI not currently supported for Darwin");
   EVT PtrVT = getPointerTy(DAG.getDataLayout());
   SDLoc dl(Op);
   const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
@@ -2873,6 +2897,8 @@ SDValue ARMTargetLowering::LowerGlobalAd
   assert(Subtarget->isTargetWindows() && "non-Windows COFF is not supported");
   assert(Subtarget->useMovt(DAG.getMachineFunction()) &&
          "Windows on ARM expects to use movw/movt");
+  assert(!Subtarget->isROPI() && !Subtarget->isRWPI() &&
+         "ROPI/RWPI not currently supported for Windows");
 
   const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
   const ARMII::TOF TargetFlags =
@@ -4123,7 +4149,7 @@ SDValue ARMTargetLowering::LowerBR_JT(SD
     return DAG.getNode(ARMISD::BR2_JT, dl, MVT::Other, Chain,
                        Addr, Op.getOperand(2), JTI);
   }
-  if (isPositionIndependent()) {
+  if (isPositionIndependent() || Subtarget->isROPI()) {
     Addr =
         DAG.getLoad((EVT)MVT::i32, dl, Chain, Addr,
                     MachinePointerInfo::getJumpTable(DAG.getMachineFunction()));
@@ -7271,6 +7297,8 @@ void ARMTargetLowering::SetupEntryBlockF
                                                MachineBasicBlock *MBB,
                                                MachineBasicBlock *DispatchBB,
                                                int FI) const {
+  assert(!Subtarget->isROPI() && !Subtarget->isRWPI() &&
+         "ROPI/RWPI not currently supported with SjLj");
   const TargetInstrInfo *TII = Subtarget->getInstrInfo();
   DebugLoc dl = MI.getDebugLoc();
   MachineFunction *MF = MBB->getParent();

Modified: llvm/trunk/lib/Target/ARM/ARMSubtarget.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMSubtarget.cpp?rev=278015&r1=278014&r2=278015&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMSubtarget.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMSubtarget.cpp Mon Aug  8 10:28:31 2016
@@ -199,6 +199,9 @@ void ARMSubtarget::initSubtargetFeatures
       (Options.UnsafeFPMath || isTargetDarwin()))
     UseNEONForSinglePrecisionFP = true;
 
+  if (isRWPI())
+    ReserveR9 = true;
+
   // FIXME: Teach TableGen to deal with these instead of doing it manually here.
   switch (ARMProcFamily) {
   case Others:
@@ -261,6 +264,15 @@ bool ARMSubtarget::isAAPCS16_ABI() const
   return TM.TargetABI == ARMBaseTargetMachine::ARM_ABI_AAPCS16;
 }
 
+bool ARMSubtarget::isROPI() const {
+  return TM.getRelocationModel() == Reloc::ROPI ||
+         TM.getRelocationModel() == Reloc::ROPI_RWPI;
+}
+bool ARMSubtarget::isRWPI() const {
+  return TM.getRelocationModel() == Reloc::RWPI ||
+         TM.getRelocationModel() == Reloc::ROPI_RWPI;
+}
+
 bool ARMSubtarget::isGVIndirectSymbol(const GlobalValue *GV) const {
   if (!TM.shouldAssumeDSOLocal(*GV->getParent(), GV))
     return true;

Modified: llvm/trunk/lib/Target/ARM/ARMSubtarget.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMSubtarget.h?rev=278015&r1=278014&r2=278015&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMSubtarget.h (original)
+++ llvm/trunk/lib/Target/ARM/ARMSubtarget.h Mon Aug  8 10:28:31 2016
@@ -544,6 +544,9 @@ public:
   bool isAAPCS_ABI() const;
   bool isAAPCS16_ABI() const;
 
+  bool isROPI() const;
+  bool isRWPI() const;
+
   bool useSoftFloat() const { return UseSoftFloat; }
   bool isThumb() const { return InThumbMode; }
   bool isThumb1Only() const { return InThumbMode && !HasThumb2; }

Modified: llvm/trunk/lib/Target/ARM/ARMTargetMachine.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMTargetMachine.cpp?rev=278015&r1=278014&r2=278015&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMTargetMachine.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMTargetMachine.cpp Mon Aug  8 10:28:31 2016
@@ -184,6 +184,10 @@ static Reloc::Model getEffectiveRelocMod
     // Default relocation model on Darwin is PIC.
     return TT.isOSBinFormatMachO() ? Reloc::PIC_ : Reloc::Static;
 
+  if (*RM == Reloc::ROPI || *RM == Reloc::RWPI || *RM == Reloc::ROPI_RWPI)
+    assert(TT.isOSBinFormatELF() &&
+           "ROPI/RWPI currently only supported for ELF");
+
   // DynamicNoPIC is only used on darwin.
   if (*RM == Reloc::DynamicNoPIC && !TT.isOSDarwin())
     return Reloc::Static;

Modified: llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp?rev=278015&r1=278014&r2=278015&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp (original)
+++ llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp Mon Aug  8 10:28:31 2016
@@ -242,10 +242,26 @@ unsigned ARMELFObjectWriter::GetRelocTyp
       Type = ELF::R_ARM_JUMP24;
       break;
     case ARM::fixup_arm_movt_hi16:
-      Type = ELF::R_ARM_MOVT_ABS;
+      switch (Modifier) {
+      default: llvm_unreachable("Unsupported Modifier");
+      case MCSymbolRefExpr::VK_None:
+        Type = ELF::R_ARM_MOVT_ABS;
+        break;
+      case MCSymbolRefExpr::VK_ARM_SBREL:
+        Type = ELF:: R_ARM_MOVT_BREL;
+        break;
+      }
       break;
     case ARM::fixup_arm_movw_lo16:
-      Type = ELF::R_ARM_MOVW_ABS_NC;
+      switch (Modifier) {
+      default: llvm_unreachable("Unsupported Modifier");
+      case MCSymbolRefExpr::VK_None:
+        Type = ELF::R_ARM_MOVW_ABS_NC;
+        break;
+      case MCSymbolRefExpr::VK_ARM_SBREL:
+        Type = ELF:: R_ARM_MOVW_BREL_NC;
+        break;
+      }
       break;
     case ARM::fixup_t2_movt_hi16:
       Type = ELF::R_ARM_THM_MOVT_ABS;

Modified: llvm/trunk/lib/Target/TargetLoweringObjectFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/TargetLoweringObjectFile.cpp?rev=278015&r1=278014&r2=278015&view=diff
==============================================================================
--- llvm/trunk/lib/Target/TargetLoweringObjectFile.cpp (original)
+++ llvm/trunk/lib/Target/TargetLoweringObjectFile.cpp Mon Aug  8 10:28:31 2016
@@ -208,12 +208,13 @@ SectionKind TargetLoweringObjectFile::ge
       }
 
     } else {
-      // In static relocation model, the linker will resolve all addresses, so
-      // the relocation entries will actually be constants by the time the app
-      // starts up.  However, we can't put this into a mergable section, because
-      // the linker doesn't take relocations into consideration when it tries to
-      // merge entries in the section.
-      if (ReloModel == Reloc::Static)
+      // In static, ROPI and RWPI relocation models, the linker will resolve
+      // all addresses, so the relocation entries will actually be constants by
+      // the time the app starts up.  However, we can't put this into a
+      // mergable section, because the linker doesn't take relocations into
+      // consideration when it tries to merge entries in the section.
+      if (ReloModel == Reloc::Static || ReloModel == Reloc::ROPI ||
+          ReloModel == Reloc::RWPI || ReloModel == Reloc::ROPI_RWPI)
         return SectionKind::getReadOnly();
 
       // Otherwise, the dynamic linker needs to fix it up, put it in the

Added: llvm/trunk/test/CodeGen/ARM/arm-position-independence-jump-table.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/arm-position-independence-jump-table.ll?rev=278015&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/arm-position-independence-jump-table.ll (added)
+++ llvm/trunk/test/CodeGen/ARM/arm-position-independence-jump-table.ll Mon Aug  8 10:28:31 2016
@@ -0,0 +1,114 @@
+; Test for generation of jump table for ropi/rwpi
+
+; RUN: llc -relocation-model=static    -mtriple=armv7a--none-eabi -disable-block-placement < %s | FileCheck %s --check-prefix=CHECK --check-prefix=ARM --check-prefix=ARM_ABS
+; RUN: llc -relocation-model=ropi      -mtriple=armv7a--none-eabi -disable-block-placement < %s | FileCheck %s --check-prefix=CHECK --check-prefix=ARM --check-prefix=ARM_PC
+; RUN: llc -relocation-model=ropi-rwpi -mtriple=armv7a--none-eabi -disable-block-placement < %s | FileCheck %s --check-prefix=CHECK --check-prefix=ARM --check-prefix=ARM_PC
+
+; RUN: llc -relocation-model=static    -mtriple=thumbv7m--none-eabi -disable-block-placement < %s | FileCheck %s --check-prefix=CHECK --check-prefix=THUMB2
+; RUN: llc -relocation-model=ropi      -mtriple=thumbv7m--none-eabi -disable-block-placement < %s | FileCheck %s --check-prefix=CHECK --check-prefix=THUMB2
+; RUN: llc -relocation-model=ropi-rwpi -mtriple=thumbv7m--none-eabi -disable-block-placement < %s | FileCheck %s --check-prefix=CHECK --check-prefix=THUMB2
+
+; RUN: llc -relocation-model=static    -mtriple=thumbv6m--none-eabi -disable-block-placement < %s | FileCheck %s --check-prefix=CHECK --check-prefix=THUMB1 --check-prefix=THUMB1_ABS
+; RUN: llc -relocation-model=ropi      -mtriple=thumbv6m--none-eabi -disable-block-placement < %s | FileCheck %s --check-prefix=CHECK --check-prefix=THUMB1 --check-prefix=THUMB1_PC
+; RUN: llc -relocation-model=ropi-rwpi -mtriple=thumbv6m--none-eabi -disable-block-placement < %s | FileCheck %s --check-prefix=CHECK --check-prefix=THUMB1 --check-prefix=THUMB1_PC
+
+
+declare void @exit0()
+declare void @exit1()
+declare void @exit2()
+declare void @exit3()
+declare void @exit4()
+define void @jump_table(i32 %val) {
+entry:
+  switch i32 %val, label %default [ i32 1, label %lab1
+                                    i32 2, label %lab2
+                                    i32 3, label %lab3
+                                    i32 4, label %lab4 ]
+
+default:
+  tail call void @exit0()
+  ret void
+
+lab1:
+  tail call void @exit1()
+  ret void
+
+lab2:
+  tail call void @exit2()
+  ret void
+
+lab3:
+  tail call void @exit3()
+  ret void
+
+lab4:
+  tail call void @exit4()
+  ret void
+
+; CHECK-LABEL: jump_table:
+
+; ARM: lsl     r[[R_TAB_IDX:[0-9]+]], r{{[0-9]+}}, #2
+; ARM: adr     r[[R_TAB_BASE:[0-9]+]], [[LJTI:\.LJTI[0-9]+_[0-9]+]]
+; ARM_ABS: ldr     pc, [r[[R_TAB_IDX]], r[[R_TAB_BASE]]]
+; ARM_PC:  ldr     r[[R_OFFSET:[0-9]+]], [r[[R_TAB_IDX]], r[[R_TAB_BASE]]]
+; ARM_PC:  add     pc, r[[R_OFFSET]], r[[R_TAB_BASE]]
+; ARM: [[LJTI]]
+; ARM_ABS: .long [[LBB1:\.LBB[0-9]+_[0-9]+]]
+; ARM_ABS: .long [[LBB2:\.LBB[0-9]+_[0-9]+]]
+; ARM_ABS: .long [[LBB3:\.LBB[0-9]+_[0-9]+]]
+; ARM_ABS: .long [[LBB4:\.LBB[0-9]+_[0-9]+]]
+; ARM_PC:  .long [[LBB1:\.LBB[0-9]+_[0-9]+]]-[[LJTI]]
+; ARM_PC:  .long [[LBB2:\.LBB[0-9]+_[0-9]+]]-[[LJTI]]
+; ARM_PC:  .long [[LBB3:\.LBB[0-9]+_[0-9]+]]-[[LJTI]]
+; ARM_PC:  .long [[LBB4:\.LBB[0-9]+_[0-9]+]]-[[LJTI]]
+; ARM: [[LBB1]]
+; ARM-NEXT: b exit1
+; ARM: [[LBB2]]
+; ARM-NEXT: b exit2
+; ARM: [[LBB3]]
+; ARM-NEXT: b exit3
+; ARM: [[LBB4]]
+; ARM-NEXT: b exit4
+
+; THUMB2: [[LCPI:\.LCPI[0-9]+_[0-9]+]]:
+; THUMB2: tbb     [pc, r{{[0-9]+}}]
+; THUMB2: .byte   ([[LBB1:\.LBB[0-9]+_[0-9]+]]-([[LCPI]]+4))/2
+; THUMB2: .byte   ([[LBB2:\.LBB[0-9]+_[0-9]+]]-([[LCPI]]+4))/2
+; THUMB2: .byte   ([[LBB3:\.LBB[0-9]+_[0-9]+]]-([[LCPI]]+4))/2
+; THUMB2: .byte   ([[LBB4:\.LBB[0-9]+_[0-9]+]]-([[LCPI]]+4))/2
+; THUMB2: [[LBB1]]
+; THUMB2-NEXT: b exit1
+; THUMB2: [[LBB2]]
+; THUMB2-NEXT: b exit2
+; THUMB2: [[LBB3]]
+; THUMB2-NEXT: b exit3
+; THUMB2: [[LBB4]]
+; THUMB2-NEXT: b exit4
+
+; THUMB1: lsls    r[[R_TAB_INDEX:[0-9]+]], r{{[0-9]+}}, #2 
+; THUMB1: adr     r[[R_TAB_BASE:[0-9]+]], [[LJTI:\.LJTI[0-9]+_[0-9]+]]
+; THUMB1: ldr     r[[R_BB_ADDR:[0-9]+]], [r[[R_TAB_INDEX]], r[[R_TAB_BASE]]]
+; THUMB1_PC: adds    r[[R_BB_ADDR]], r[[R_BB_ADDR]], r[[R_TAB_BASE]]
+; THUMB1: mov     pc, r[[R_BB_ADDR]]
+; THUMB1: [[LJTI]]
+; THUMB1_ABS: .long [[LBB1:\.LBB[0-9]+_[0-9]+]]+1
+; THUMB1_ABS: .long [[LBB2:\.LBB[0-9]+_[0-9]+]]+1
+; THUMB1_ABS: .long [[LBB3:\.LBB[0-9]+_[0-9]+]]+1
+; THUMB1_ABS: .long [[LBB4:\.LBB[0-9]+_[0-9]+]]+1
+; THUMB1_PC:  .long [[LBB1:\.LBB[0-9]+_[0-9]+]]-[[LJTI]]
+; THUMB1_PC:  .long [[LBB2:\.LBB[0-9]+_[0-9]+]]-[[LJTI]]
+; THUMB1_PC:  .long [[LBB3:\.LBB[0-9]+_[0-9]+]]-[[LJTI]]
+; THUMB1_PC:  .long [[LBB4:\.LBB[0-9]+_[0-9]+]]-[[LJTI]]
+; THUMB1: [[LBB1]]
+; THUMB1-NEXT: bl exit1
+; THUMB1-NEXT: pop
+; THUMB1: [[LBB2]]
+; THUMB1-NEXT: bl exit2
+; THUMB1-NEXT: pop
+; THUMB1: [[LBB3]]
+; THUMB1-NEXT: bl exit3
+; THUMB1-NEXT: pop
+; THUMB1: [[LBB4]]
+; THUMB1-NEXT: bl exit4
+; THUMB1-NEXT: pop
+}

Added: llvm/trunk/test/CodeGen/ARM/arm-position-independence.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/arm-position-independence.ll?rev=278015&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/arm-position-independence.ll (added)
+++ llvm/trunk/test/CodeGen/ARM/arm-position-independence.ll Mon Aug  8 10:28:31 2016
@@ -0,0 +1,309 @@
+; RUN: llc -relocation-model=static    -mtriple=armv7a--none-eabi < %s | FileCheck %s --check-prefix=CHECK --check-prefix=ARM_RO_ABS --check-prefix=ARM_RW_ABS
+; RUN: llc -relocation-model=ropi      -mtriple=armv7a--none-eabi < %s | FileCheck %s --check-prefix=CHECK --check-prefix=ARM_RO_PC  --check-prefix=ARM_RW_ABS
+; RUN: llc -relocation-model=rwpi      -mtriple=armv7a--none-eabi < %s | FileCheck %s --check-prefix=CHECK --check-prefix=ARM_RO_ABS --check-prefix=ARM_RW_SB
+; RUN: llc -relocation-model=ropi-rwpi -mtriple=armv7a--none-eabi < %s | FileCheck %s --check-prefix=CHECK --check-prefix=ARM_RO_PC  --check-prefix=ARM_RW_SB
+
+; RUN: llc -relocation-model=static    -mtriple=thumbv7m--none-eabi < %s | FileCheck %s --check-prefix=CHECK --check-prefix=THUMB2_RO_ABS --check-prefix=THUMB2_RW_ABS
+; RUN: llc -relocation-model=ropi      -mtriple=thumbv7m--none-eabi < %s | FileCheck %s --check-prefix=CHECK --check-prefix=THUMB2_RO_PC  --check-prefix=THUMB2_RW_ABS
+; RUN: llc -relocation-model=rwpi      -mtriple=thumbv7m--none-eabi < %s | FileCheck %s --check-prefix=CHECK --check-prefix=THUMB2_RO_ABS  --check-prefix=THUMB2_RW_SB
+; RUN: llc -relocation-model=ropi-rwpi -mtriple=thumbv7m--none-eabi < %s | FileCheck %s --check-prefix=CHECK --check-prefix=THUMB2_RO_PC  --check-prefix=THUMB2_RW_SB
+
+; RUN: llc -relocation-model=static    -mtriple=thumbv6m--none-eabi < %s | FileCheck %s --check-prefix=CHECK --check-prefix=THUMB1_RO_ABS --check-prefix=THUMB1_RW_ABS
+; RUN: llc -relocation-model=ropi      -mtriple=thumbv6m--none-eabi < %s | FileCheck %s --check-prefix=CHECK --check-prefix=THUMB1_RO_PC  --check-prefix=THUMB1_RW_ABS
+; RUN: llc -relocation-model=rwpi      -mtriple=thumbv6m--none-eabi < %s | FileCheck %s --check-prefix=CHECK --check-prefix=THUMB1_RO_ABS --check-prefix=THUMB1_RW_SB
+; RUN: llc -relocation-model=ropi-rwpi -mtriple=thumbv6m--none-eabi < %s | FileCheck %s --check-prefix=CHECK --check-prefix=THUMB1_RO_PC  --check-prefix=THUMB1_RW_SB
+
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
+
+ at a = external global i32, align 4
+ at b = external constant i32, align 4
+
+define i32 @read() {
+entry:
+  %0 = load i32, i32* @a, align 4
+  ret i32 %0
+; CHECK-LABEL: read:
+
+; ARM_RW_ABS: movw    r[[REG:[0-9]]], :lower16:a
+; ARM_RW_ABS: movt    r[[REG]], :upper16:a
+; ARM_RW_ABS: ldr     r0, [r[[REG]]]
+
+; ARM_RW_SB: ldr     r[[REG:[0-9]]], [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; ARM_RW_SB: ldr     r0, [r9, r[[REG]]]
+
+; THUMB2_RW_ABS: movw    r[[REG:[0-9]]], :lower16:a
+; THUMB2_RW_ABS: movt    r[[REG]], :upper16:a
+; THUMB2_RW_ABS: ldr     r0, [r[[REG]]]
+
+; THUMB2_RW_SB: ldr     r[[REG:[0-9]]], [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; THUMB2_RW_SB: ldr.w   r0, [r9, r[[REG]]]
+
+; THUMB1_RW_ABS: ldr     r[[REG:[0-9]]], [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; THUMB1_RW_ABS: ldr     r0, [r[[REG]]]
+
+; THUMB1_RW_SB: ldr     r[[REG:[0-9]]], [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; THUMB1_RW_SB: mov     r[[REG_SB:[0-9]+]], r9
+; THUMB1_RW_SB: ldr     r0, [r[[REG_SB]], r[[REG]]]
+
+; CHECK: {{(bx lr|pop)}}
+
+; ARM_RW_SB: [[LCPI]]
+; ARM_RW_SB: .long   a(sbrel)
+
+; THUMB2_RW_SB: [[LCPI]]
+; THUMB2_RW_SB: .long   a(sbrel)
+
+; THUMB1_RW_ABS: [[LCPI]]
+; THUMB1_RW_ABS-NEXT: .long a
+
+; THUMB1_RW_SB: [[LCPI]]
+; THUMB1_RW_SB: .long   a(sbrel)
+}
+
+define void @write(i32 %v)  {
+entry:
+  store i32 %v, i32* @a, align 4
+  ret void
+; CHECK-LABEL: write:
+
+; ARM_RW_ABS: movw    r[[REG:[0-9]]], :lower16:a
+; ARM_RW_ABS: movt    r[[REG]], :upper16:a
+; ARM_RW_ABS: str     r0, [r[[REG:[0-9]]]]
+
+; ARM_RW_SB: ldr     r[[REG:[0-9]]], [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; ARM_RW_SB: str     r0, [r9, r[[REG]]]
+
+; THUMB2_RW_ABS: movw    r[[REG:[0-9]]], :lower16:a
+; THUMB2_RW_ABS: movt    r[[REG]], :upper16:a
+; THUMB2_RW_ABS: str     r0, [r[[REG]]]
+
+; THUMB2_RW_SB: ldr     r[[REG:[0-9]]], [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; THUMB2_RW_SB: str.w   r0, [r9, r[[REG]]]
+
+; THUMB1_RW_ABS: ldr     r[[REG:[0-9]]], [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; THUMB1_RW_ABS: str     r0, [r[[REG]]]
+
+; THUMB1_RW_SB: ldr     r[[REG:[0-9]]], [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; THUMB1_RW_SB: mov     r[[REG_SB:[0-9]+]], r9
+; THUMB1_RW_SB: str     r0, [r[[REG_SB]], r[[REG]]]
+
+; CHECK: {{(bx lr|pop)}}
+
+; ARM_RW_SB: [[LCPI]]
+; ARM_RW_SB: .long   a(sbrel)
+
+; THUMB2_RW_SB: [[LCPI]]
+; THUMB2_RW_SB: .long   a(sbrel)
+
+; THUMB1_RW_ABS: [[LCPI]]
+; THUMB1_RW_ABS-NEXT: .long a
+
+; THUMB1_RW_SB: [[LCPI]]
+; THUMB1_RW_SB: .long   a(sbrel)
+}
+
+define i32 @read_const()  {
+entry:
+  %0 = load i32, i32* @b, align 4
+  ret i32 %0
+; CHECK-LABEL: read_const:
+
+; ARM_RO_ABS: movw    r[[reg:[0-9]]], :lower16:b
+; ARM_RO_ABS: movt    r[[reg]], :upper16:b
+; ARM_RO_ABS: ldr     r0, [r[[reg]]]
+
+; ARM_RO_PC: movw    r[[REG:[0-9]]], :lower16:(b-([[LPC:.LPC[0-9]+_[0-9]+]]+8))
+; ARM_RO_PC: movt    r[[REG]], :upper16:(b-([[LPC]]+8))
+; ARM_RO_PC: [[LPC]]:
+; ARM_RO_PC-NEXT: ldr     r0, [pc, r[[REG]]]
+
+; THUMB2_RO_ABS: movw    r[[REG:[0-9]]], :lower16:b
+; THUMB2_RO_ABS: movt    r[[REG]], :upper16:b
+; THUMB2_RO_ABS: ldr     r0, [r[[REG]]]
+
+; THUMB2_RO_PC: movw    r[[REG:[0-9]]], :lower16:(b-([[LPC:.LPC[0-9]+_[0-9]+]]+4))
+; THUMB2_RO_PC: movt    r[[REG]], :upper16:(b-([[LPC]]+4))
+; THUMB2_RO_PC: [[LPC]]:
+; THUMB2_RO_PC-NEXT: add     r[[REG]], pc
+; THUMB2_RO_PC: ldr     r0, [r[[REG]]]
+
+; THUMB1_RO_ABS: ldr     r[[REG:[0-9]]], [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; THUMB1_RO_ABS: ldr     r0, [r[[REG]]]
+
+; THUMB1_RO_PC: ldr     r[[REG:[0-9]]], [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; THUMB1_RO_PC: [[LPC:.LPC[0-9]+_[0-9]+]]:
+; THUMB1_RO_PC-NEXT: add     r[[REG]], pc
+; THUMB1_RO_PC: ldr     r0, [r[[REG]]]
+
+; CHECK: {{(bx lr|pop)}}
+
+; THUMB1_RO_ABS: [[LCPI]]
+; THUMB1_RO_ABS-NEXT: .long b
+
+; THUMB1_RO_PC: [[LCPI]]
+; THUMB1_RO_PC-NEXT: .long b-([[LPC]]+4)
+}
+
+define i32* @take_addr()  {
+entry:
+  ret i32* @a
+; CHECK-LABEL: take_addr:
+
+; ARM_RW_ABS: movw    r[[REG:[0-9]]], :lower16:a
+; ARM_RW_ABS: movt    r[[REG]], :upper16:a
+
+; ARM_RW_SB: ldr     r[[REG:[0-9]]], [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; ARM_RW_SB: add     r0, r9, r[[REG]]
+
+; THUMB2_RW_ABS: movw    r[[REG:[0-9]]], :lower16:a
+; THUMB2_RW_ABS: movt    r[[REG]], :upper16:a
+
+; THUMB2_RW_SB: ldr     r0, [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; THUMB2_RW_SB: add     r0, r9
+
+; THUMB1_RW_ABS: ldr     r0, [[LCPI:.LCPI[0-9]+_[0-9]+]]
+
+; THUMB1_RW_SB: ldr     r[[REG:[0-9]]], [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; THUMB1_RW_SB: mov     r[[REG_SB:[0-9]+]], r9
+; THUMB1_RW_SB: adds    r[[REG]], r[[REG_SB]], r[[REG]]
+
+; CHECK: {{(bx lr|pop)}}
+
+; ARM_RW_SB: [[LCPI]]
+; ARM_RW_SB: .long   a(sbrel)
+
+; THUMB2_RW_SB: [[LCPI]]
+; THUMB2_RW_SB: .long   a(sbrel)
+
+; THUMB1_RW_ABS: [[LCPI]]
+; THUMB1_RW_ABS-NEXT: .long a
+
+; THUMB1_RW_SB: [[LCPI]]
+; THUMB1_RW_SB: .long   a(sbrel)
+}
+
+define i32* @take_addr_const()  {
+entry:
+  ret i32* @b
+; CHECK-LABEL: take_addr_const:
+
+; ARM_RO_ABS: movw    r[[REG:[0-9]]], :lower16:b
+; ARM_RO_ABS: movt    r[[REG]], :upper16:b
+
+; ARM_RO_PC: movw    r[[REG:[0-9]]], :lower16:(b-([[LPC:.LPC[0-9]+_[0-9]+]]+8))
+; ARM_RO_PC: movt    r[[REG]], :upper16:(b-([[LPC]]+8))
+; ARM_RO_PC: [[LPC]]:
+; ARM_RO_PC-NEXT: add     r0, pc, r[[REG:[0-9]]]
+
+; THUMB2_RO_ABS: movw    r[[REG:[0-9]]], :lower16:b
+; THUMB2_RO_ABS: movt    r[[REG]], :upper16:b
+
+; THUMB2_RO_PC: movw    r0, :lower16:(b-([[LPC:.LPC[0-9]+_[0-9]+]]+4))
+; THUMB2_RO_PC: movt    r0, :upper16:(b-([[LPC]]+4))
+; THUMB2_RO_PC: [[LPC]]:
+; THUMB2_RO_PC-NEXT: add     r0, pc
+
+; THUMB1_RO_ABS: ldr     r0, [[LCPI:.LCPI[0-9]+_[0-9]+]]
+
+; THUMB1_RO_PC: ldr     r[[REG:[0-9]]], [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; THUMB1_RO_PC: [[LPC:.LPC[0-9]+_[0-9]+]]:
+; THUMB1_RO_PC-NEXT: add     r[[REG]], pc
+
+; CHECK: {{(bx lr|pop)}}
+
+; THUMB1_RO_ABS: [[LCPI]]
+; THUMB1_RO_ABS-NEXT: .long b
+
+; THUMB1_RO_PC: [[LCPI]]
+; THUMB1_RO_PC-NEXT: .long b-([[LPC]]+4)
+}
+
+define i8* @take_addr_func()  {
+entry:
+  ret i8* bitcast (i8* ()* @take_addr_func to i8*)
+; CHECK-LABEL: take_addr_func:
+
+; ARM_RO_ABS: movw    r[[REG:[0-9]]], :lower16:take_addr_func
+; ARM_RO_ABS: movt    r[[REG]], :upper16:take_addr_func
+
+; ARM_RO_PC: movw    r[[REG:[0-9]]], :lower16:(take_addr_func-([[LPC:.LPC[0-9]+_[0-9]+]]+8))
+; ARM_RO_PC: movt    r[[REG]], :upper16:(take_addr_func-([[LPC]]+8))
+; ARM_RO_PC: [[LPC]]:
+; ARM_RO_PC-NEXT: add     r0, pc, r[[REG:[0-9]]]
+
+; THUMB2_RO_ABS: movw    r[[REG:[0-9]]], :lower16:take_addr_func
+; THUMB2_RO_ABS: movt    r[[REG]], :upper16:take_addr_func
+
+; THUMB2_RO_PC: movw    r0, :lower16:(take_addr_func-([[LPC:.LPC[0-9]+_[0-9]+]]+4))
+; THUMB2_RO_PC: movt    r0, :upper16:(take_addr_func-([[LPC]]+4))
+; THUMB2_RO_PC: [[LPC]]:
+; THUMB2_RO_PC-NEXT: add     r0, pc
+
+; THUMB1_RO_ABS: ldr     r0, [[LCPI:.LCPI[0-9]+_[0-9]+]]
+
+; THUMB1_RO_PC: ldr     r[[REG:[0-9]]], [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; THUMB1_RO_PC: [[LPC:.LPC[0-9]+_[0-9]+]]:
+; THUMB1_RO_PC-NEXT: add     r[[REG]], pc
+
+; CHECK: {{(bx lr|pop)}}
+
+; THUMB1_RO_ABS: [[LCPI]]
+; THUMB1_RO_ABS-NEXT: .long take_addr_func
+
+; THUMB1_RO_PC: [[LCPI]]
+; THUMB1_RO_PC-NEXT: .long take_addr_func-([[LPC]]+4)
+}
+
+define i8* @block_addr() {
+entry:
+  br label %lab1
+
+lab1:
+  ret i8* blockaddress(@block_addr, %lab1)
+
+; CHECK-LABEL: block_addr:
+
+; ARM_RO_ABS: [[LTMP:.Ltmp[0-9]+]]:
+; ARM_RO_ABS: ldr     r0, [[LCPI:.LCPI[0-9]+_[0-9]+]]
+
+; ARM_RO_PC: [[LTMP:.Ltmp[0-9]+]]:
+; ARM_RO_PC: ldr     r[[REG:[0-9]]], [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; ARM_RO_PC: [[LPC:.LPC[0-9]+_[0-9]+]]:
+; ARM_RO_PC: add     r0, pc, r[[REG]]
+
+; THUMB2_RO_ABS: [[LTMP:.Ltmp[0-9]+]]:
+; THUMB2_RO_ABS: ldr     r0, [[LCPI:.LCPI[0-9]+_[0-9]+]]
+
+; THUMB2_RO_PC: [[LTMP:.Ltmp[0-9]+]]:
+; THUMB2_RO_PC: ldr     r0, [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; THUMB2_RO_PC: [[LPC:.LPC[0-9]+_[0-9]+]]:
+; THUMB2_RO_PC: add     r0, pc
+
+; THUMB1_RO_ABS: [[LTMP:.Ltmp[0-9]+]]:
+; THUMB1_RO_ABS: ldr     r0, [[LCPI:.LCPI[0-9]+_[0-9]+]]
+
+; THUMB1_RO_PC: [[LTMP:.Ltmp[0-9]+]]:
+; THUMB1_RO_PC: ldr     r0, [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; THUMB1_RO_PC: [[LPC:.LPC[0-9]+_[0-9]+]]:
+; THUMB1_RO_PC: add     r0, pc
+
+; CHECK: bx lr
+
+; ARM_RO_ABS: [[LCPI]]
+; ARM_RO_ABS-NEXT: .long   [[LTMP]]
+
+; ARM_RO_PC: [[LCPI]]
+; ARM_RO_PC-NEXT: .long   [[LTMP]]-([[LPC]]+8)
+
+; THUMB2_RO_ABS: [[LCPI]]
+; THUMB2_RO_ABS-NEXT: .long   [[LTMP]]
+
+; THUMB2_RO_PC: [[LCPI]]
+; THUMB2_RO_PC-NEXT: .long   [[LTMP]]-([[LPC]]+4)
+
+; THUMB1_RO_ABS: [[LCPI]]
+; THUMB1_RO_ABS-NEXT: .long   [[LTMP]]
+
+; THUMB1_RO_PC: [[LCPI]]
+; THUMB1_RO_PC-NEXT: .long   [[LTMP]]-([[LPC]]+4)
+}

Modified: llvm/trunk/test/CodeGen/ARM/build-attributes.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/build-attributes.ll?rev=278015&r1=278014&r2=278015&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/build-attributes.ll (original)
+++ llvm/trunk/test/CodeGen/ARM/build-attributes.ll Mon Aug  8 10:28:31 2016
@@ -147,6 +147,9 @@
 ; RUN: llc < %s -mtriple=arm-none-linux-gnueabi -mattr=+strict-align | FileCheck %s --check-prefix=RELOC-OTHER
 ; RUN: llc < %s -mtriple=arm-none-linux-gnueabi -mattr=+strict-align | FileCheck %s --check-prefix=PCS-R9-USE
 ; RUN: llc < %s -mtriple=arm-none-linux-gnueabi -mattr=+reserve-r9,+strict-align | FileCheck %s --check-prefix=PCS-R9-RESERVE
+; RUN: llc < %s -mtriple=arm-none-linux-gnueabi -mattr=+strict-align -relocation-model=ropi | FileCheck %s --check-prefix=RELOC-ROPI
+; RUN: llc < %s -mtriple=arm-none-linux-gnueabi -mattr=+strict-align -relocation-model=rwpi | FileCheck %s --check-prefix=RELOC-RWPI
+; RUN: llc < %s -mtriple=arm-none-linux-gnueabi -mattr=+strict-align -relocation-model=ropi-rwpi | FileCheck %s --check-prefix=RELOC-ROPI-RWPI
 
 ; ARMv8.1a (AArch32)
 ; RUN: llc < %s -mtriple=armv8.1a-none-linux-gnueabi | FileCheck %s --check-prefix=NO-STRICT-ALIGN
@@ -1522,6 +1525,15 @@
 ; RELOC-PIC:  .eabi_attribute 16, 1
 ; RELOC-PIC:  .eabi_attribute 17, 2
 ; RELOC-OTHER:  .eabi_attribute 17, 1
+; RELOC-ROPI-NOT:  .eabi_attribute 15,
+; RELOC-ROPI:      .eabi_attribute 16, 1
+; RELOC-ROPI:      .eabi_attribute 17, 1
+; RELOC-RWPI:      .eabi_attribute 15, 2
+; RELOC-RWPI-NOT:  .eabi_attribute 16,
+; RELOC-RWPI:      .eabi_attribute 17, 1
+; RELOC-ROPI-RWPI: .eabi_attribute 15, 2
+; RELOC-ROPI-RWPI: .eabi_attribute 16, 1
+; RELOC-ROPI-RWPI:  .eabi_attribute 17, 1
 
 ; PCS-R9-USE:  .eabi_attribute 14, 0
 ; PCS-R9-RESERVE:  .eabi_attribute 14, 3




More information about the llvm-commits mailing list