diff options
| author | Oliver Stannard <oliver.stannard@arm.com> | 2016-08-08 15:28:31 +0000 |
|---|---|---|
| committer | Oliver Stannard <oliver.stannard@arm.com> | 2016-08-08 15:28:31 +0000 |
| commit | 8331aaee8fb9172ddf0cb45c4b04cb76fe224da4 (patch) | |
| tree | c5549f749c7cf270e5e3b0c5cfc25490a0fad3d3 | |
| parent | 219feac45643d92784186bcee627d940775b596b (diff) | |
| download | bcm5719-llvm-8331aaee8fb9172ddf0cb45c4b04cb76fe224da4.tar.gz bcm5719-llvm-8331aaee8fb9172ddf0cb45c4b04cb76fe224da4.zip | |
[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
llvm-svn: 278015
| -rw-r--r-- | llvm/include/llvm/CodeGen/CommandFlags.h | 6 | ||||
| -rw-r--r-- | llvm/include/llvm/Support/CodeGen.h | 2 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/ARMAsmPrinter.cpp | 35 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp | 3 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/ARMConstantPoolValue.cpp | 2 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/ARMConstantPoolValue.h | 1 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/ARMFastISel.cpp | 4 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/ARMISelLowering.cpp | 32 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/ARMSubtarget.cpp | 12 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/ARMSubtarget.h | 3 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/ARMTargetMachine.cpp | 4 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp | 20 | ||||
| -rw-r--r-- | llvm/lib/Target/TargetLoweringObjectFile.cpp | 13 | ||||
| -rw-r--r-- | llvm/test/CodeGen/ARM/arm-position-independence-jump-table.ll | 114 | ||||
| -rw-r--r-- | llvm/test/CodeGen/ARM/arm-position-independence.ll | 309 | ||||
| -rw-r--r-- | llvm/test/CodeGen/ARM/build-attributes.ll | 12 |
16 files changed, 551 insertions, 21 deletions
diff --git a/llvm/include/llvm/CodeGen/CommandFlags.h b/llvm/include/llvm/CodeGen/CommandFlags.h index 7c1dc6f7644..4c05e7fd9e0 100644 --- a/llvm/include/llvm/CodeGen/CommandFlags.h +++ b/llvm/include/llvm/CodeGen/CommandFlags.h @@ -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() { diff --git a/llvm/include/llvm/Support/CodeGen.h b/llvm/include/llvm/Support/CodeGen.h index e19abf8271e..941c112b0dd 100644 --- a/llvm/include/llvm/Support/CodeGen.h +++ b/llvm/include/llvm/Support/CodeGen.h @@ -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. diff --git a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp index 04863a7ecf8..e2d3821a705 100644 --- a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp +++ b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp @@ -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::ARMCPModifier Modifier) { 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(const MachineInstr *MI) { // .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); diff --git a/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp b/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp index 043a3d4575f..9e0a49935fc 100644 --- a/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp +++ b/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -4119,6 +4119,9 @@ bool ARMBaseInstrInfo::verifyInstruction(const MachineInstr &MI, 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(); diff --git a/llvm/lib/Target/ARM/ARMConstantPoolValue.cpp b/llvm/lib/Target/ARM/ARMConstantPoolValue.cpp index c0db001cb6f..f13ae481bdb 100644 --- a/llvm/lib/Target/ARM/ARMConstantPoolValue.cpp +++ b/llvm/lib/Target/ARM/ARMConstantPoolValue.cpp @@ -60,6 +60,8 @@ const char *ARMConstantPoolValue::getModifierText() const { return "gottpoff"; case ARMCP::TPOFF: return "tpoff"; + case ARMCP::SBREL: + return "SBREL"; case ARMCP::SECREL: return "secrel32"; } diff --git a/llvm/lib/Target/ARM/ARMConstantPoolValue.h b/llvm/lib/Target/ARM/ARMConstantPoolValue.h index c07331d71da..fae64dc2455 100644 --- a/llvm/lib/Target/ARM/ARMConstantPoolValue.h +++ b/llvm/lib/Target/ARM/ARMConstantPoolValue.h @@ -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) }; } diff --git a/llvm/lib/Target/ARM/ARMFastISel.cpp b/llvm/lib/Target/ARM/ARMFastISel.cpp index 165a8be1c29..816d7b7b6a8 100644 --- a/llvm/lib/Target/ARM/ARMFastISel.cpp +++ b/llvm/lib/Target/ARM/ARMFastISel.cpp @@ -546,6 +546,10 @@ unsigned ARMFastISel::ARMMaterializeGV(const GlobalValue *GV, MVT VT) { // 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; diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp index 0987eb225f1..e505a75198e 100644 --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -2530,7 +2530,7 @@ SDValue ARMTargetLowering::LowerBlockAddress(SDValue Op, 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::LowerGlobalAddressELF(SDValue Op, 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::LowerGlobalAddressELF(SDValue Op, 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::LowerGlobalAddressELF(SDValue Op, 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::LowerGlobalAddressWindows(SDValue Op, 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(SDValue Op, SelectionDAG &DAG) const { 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::SetupEntryBlockForSjLj(MachineInstr &MI, 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(); diff --git a/llvm/lib/Target/ARM/ARMSubtarget.cpp b/llvm/lib/Target/ARM/ARMSubtarget.cpp index 1d7eef9ddcf..561f80ad21f 100644 --- a/llvm/lib/Target/ARM/ARMSubtarget.cpp +++ b/llvm/lib/Target/ARM/ARMSubtarget.cpp @@ -199,6 +199,9 @@ void ARMSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) { (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; diff --git a/llvm/lib/Target/ARM/ARMSubtarget.h b/llvm/lib/Target/ARM/ARMSubtarget.h index 910de0e1e72..97bce6fa8ff 100644 --- a/llvm/lib/Target/ARM/ARMSubtarget.h +++ b/llvm/lib/Target/ARM/ARMSubtarget.h @@ -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; } diff --git a/llvm/lib/Target/ARM/ARMTargetMachine.cpp b/llvm/lib/Target/ARM/ARMTargetMachine.cpp index dc730a675be..066587aabd7 100644 --- a/llvm/lib/Target/ARM/ARMTargetMachine.cpp +++ b/llvm/lib/Target/ARM/ARMTargetMachine.cpp @@ -184,6 +184,10 @@ static Reloc::Model getEffectiveRelocModel(const Triple &TT, // 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; diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp index bb562df1b28..fa468ea1501 100644 --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp @@ -242,10 +242,26 @@ unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target, 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; diff --git a/llvm/lib/Target/TargetLoweringObjectFile.cpp b/llvm/lib/Target/TargetLoweringObjectFile.cpp index f863f429f43..3be4c1d5155 100644 --- a/llvm/lib/Target/TargetLoweringObjectFile.cpp +++ b/llvm/lib/Target/TargetLoweringObjectFile.cpp @@ -208,12 +208,13 @@ SectionKind TargetLoweringObjectFile::getKindForGlobal(const GlobalValue *GV, } } 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 diff --git a/llvm/test/CodeGen/ARM/arm-position-independence-jump-table.ll b/llvm/test/CodeGen/ARM/arm-position-independence-jump-table.ll new file mode 100644 index 00000000000..507f399c1f7 --- /dev/null +++ b/llvm/test/CodeGen/ARM/arm-position-independence-jump-table.ll @@ -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 +} diff --git a/llvm/test/CodeGen/ARM/arm-position-independence.ll b/llvm/test/CodeGen/ARM/arm-position-independence.ll new file mode 100644 index 00000000000..02a63984ad6 --- /dev/null +++ b/llvm/test/CodeGen/ARM/arm-position-independence.ll @@ -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" + +@a = external global i32, align 4 +@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) +} diff --git a/llvm/test/CodeGen/ARM/build-attributes.ll b/llvm/test/CodeGen/ARM/build-attributes.ll index 990db8a00c4..53b8fc39a7c 100644 --- a/llvm/test/CodeGen/ARM/build-attributes.ll +++ b/llvm/test/CodeGen/ARM/build-attributes.ll @@ -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 |

