]> granicus.if.org Git - llvm/commitdiff
[ARM] Make RWPI use movw/movt when available
authorChristof Douma <Christof.Douma@arm.com>
Tue, 7 Feb 2017 13:07:12 +0000 (13:07 +0000)
committerChristof Douma <Christof.Douma@arm.com>
Tue, 7 Feb 2017 13:07:12 +0000 (13:07 +0000)
When constructing global address literals while targeting the RWPI
relocation model. LLVM currently only uses literal pools. If MOVW/MOVT
instructions are available we can use these instead. Beside being more
efficient it allows -arm-execute-only to work with
-relocation-model=RWPI as well.

When we generate MOVW/MOVT for global addresses when targeting the RWPI
relocation model, we need to use base relative relocations. This patch
does the needed plumbing in MC to generate these for MOVW/MOVT.

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

Change-Id: I446786e43a6f5aa9b6a5bb2cd216d60d41c7755d

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@294298 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/ARMISelLowering.cpp
lib/Target/ARM/ARMMCInstLower.cpp
lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h
lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp
test/CodeGen/ARM/arm-position-independence.ll

index ad117dc802730818a938291bfcbf99ab348ed781..f21b8757eaedfb5e0d83893c2fdcf5c687200d80 100644 (file)
@@ -3111,15 +3111,22 @@ SDValue ARMTargetLowering::LowerGlobalAddressELF(SDValue Op,
     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 RelAddr;
+    if (Subtarget->useMovt(DAG.getMachineFunction())) {
+      ++NumMovwMovt;
+      SDValue G = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, ARMII::MO_SBREL);
+      RelAddr = DAG.getNode(ARMISD::Wrapper, dl, PtrVT, G);
+    } else { // use literal pool for address constant
+      ARMConstantPoolValue *CPV =
+        ARMConstantPoolConstant::Create(GV, ARMCP::SBREL);
+      SDValue CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, 4);
+      CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
+      RelAddr = 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);
+    SDValue Result = DAG.getNode(ISD::ADD, dl, PtrVT, SB, RelAddr);
     return Result;
   }
 
index bbfd2a62464fc9748abe2777f3a842fd4e7a92e4..0fd98268723ab49c4823b5148ebd3cb35c4ea1d8 100644 (file)
@@ -38,8 +38,12 @@ using namespace llvm;
 
 MCOperand ARMAsmPrinter::GetSymbolRef(const MachineOperand &MO,
                                       const MCSymbol *Symbol) {
+  MCSymbolRefExpr::VariantKind SymbolVariant = MCSymbolRefExpr::VK_None;
+  if (MO.getTargetFlags() & ARMII::MO_SBREL)
+    SymbolVariant = MCSymbolRefExpr::VK_ARM_SBREL;
+
   const MCExpr *Expr =
-      MCSymbolRefExpr::create(Symbol, MCSymbolRefExpr::VK_None, OutContext);
+      MCSymbolRefExpr::create(Symbol, SymbolVariant, OutContext);
   switch (MO.getTargetFlags() & ARMII::MO_OPTION_MASK) {
   default:
     llvm_unreachable("Unknown target flag on symbol operand");
@@ -47,12 +51,12 @@ MCOperand ARMAsmPrinter::GetSymbolRef(const MachineOperand &MO,
     break;
   case ARMII::MO_LO16:
     Expr =
-        MCSymbolRefExpr::create(Symbol, MCSymbolRefExpr::VK_None, OutContext);
+        MCSymbolRefExpr::create(Symbol, SymbolVariant, OutContext);
     Expr = ARMMCExpr::createLower16(Expr, OutContext);
     break;
   case ARMII::MO_HI16:
     Expr =
-        MCSymbolRefExpr::create(Symbol, MCSymbolRefExpr::VK_None, OutContext);
+        MCSymbolRefExpr::create(Symbol, SymbolVariant, OutContext);
     Expr = ARMMCExpr::createUpper16(Expr, OutContext);
     break;
   }
index 088b4205ed624582dd3e52d19b8b7987e4f36c30..92e553f21f14386ac1db621c21163197665f6c70 100644 (file)
@@ -291,7 +291,11 @@ namespace ARMII {
 
     /// MO_OPTION_MASK - Most flags are mutually exclusive; this mask selects
     /// just that part of the flag set.
-    MO_OPTION_MASK = 0x1f,
+    MO_OPTION_MASK = 0x0f,
+
+    /// MO_SBREL - On a symbol operand, this represents a static base relative
+    /// relocation. Used in movw and movt instructions.
+    MO_SBREL = 0x10,
 
     /// MO_DLLIMPORT - On a symbol operand, this represents that the reference
     /// to the symbol is for an import stub.  This is used for DLL import
index 2c947541322052de3e302e1a3f17bc66b477deaf..c921e4cf78284d6cd62707cee85cd52a61929c70 100644 (file)
@@ -269,10 +269,26 @@ unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target,
       }
       break;
     case ARM::fixup_t2_movt_hi16:
-      Type = ELF::R_ARM_THM_MOVT_ABS;
+      switch (Modifier) {
+      default: llvm_unreachable("Unsupported Modifier");
+      case MCSymbolRefExpr::VK_None:
+        Type = ELF::R_ARM_THM_MOVT_ABS;
+        break;
+      case MCSymbolRefExpr::VK_ARM_SBREL:
+        Type = ELF:: R_ARM_THM_MOVT_BREL;
+        break;
+      }
       break;
     case ARM::fixup_t2_movw_lo16:
-      Type = ELF::R_ARM_THM_MOVW_ABS_NC;
+      switch (Modifier) {
+      default: llvm_unreachable("Unsupported Modifier");
+      case MCSymbolRefExpr::VK_None:
+        Type = ELF::R_ARM_THM_MOVW_ABS_NC;
+        break;
+      case MCSymbolRefExpr::VK_ARM_SBREL:
+        Type = ELF:: R_ARM_THM_MOVW_BREL_NC;
+        break;
+      }
       break;
     }
   }
index 02a63984ad6f443b690dccc17dbf07da63a4fad1..4aa817f7a481469022859d307a75dd3d05046710 100644 (file)
 ; 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
 
+; RUN: llc -relocation-model=rwpi      -mtriple=armv7a--none-eabi   -mattr=no-movt < %s | FileCheck %s --check-prefix=CHECK --check-prefix=NO_MOVT_ARM_RO_ABS --check-prefix=NO_MOVT_ARM_RW_SB
+; RUN: llc -relocation-model=ropi-rwpi -mtriple=armv7a--none-eabi   -mattr=no-movt < %s | FileCheck %s --check-prefix=CHECK --check-prefix=NO_MOVT_ARM_RO_PC  --check-prefix=NO_MOVT_ARM_RW_SB
+
+; RUN: llc -relocation-model=rwpi      -mtriple=thumbv7m--none-eabi -mattr=no-movt < %s | FileCheck %s --check-prefix=CHECK --check-prefix=NO_MOVT_THUMB2_RO_ABS  --check-prefix=NO_MOVT_THUMB2_RW_SB
+; RUN: llc -relocation-model=ropi-rwpi -mtriple=thumbv7m--none-eabi -mattr=no-movt < %s | FileCheck %s --check-prefix=CHECK --check-prefix=NO_MOVT_THUMB2_RO_PC  --check-prefix=NO_MOVT_THUMB2_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
@@ -28,16 +34,24 @@ entry:
 ; 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: movw    r[[REG:[0-9]]], :lower16:a(sbrel)
+; ARM_RW_SB: movt    r[[REG]], :upper16:a(sbrel)
 ; ARM_RW_SB: ldr     r0, [r9, r[[REG]]]
 
+; NO_MOVT_ARM_RW_SB: ldr     r[[REG:[0-9]]], [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; NO_MOVT_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: movw    r[[REG:[0-9]]], :lower16:a(sbrel)
+; THUMB2_RW_SB: movt    r[[REG]], :upper16:a(sbrel)
 ; THUMB2_RW_SB: ldr.w   r0, [r9, r[[REG]]]
 
+; NO_MOVT_THUMB2_RW_SB: ldr     r[[REG:[0-9]]], [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; NO_MOVT_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]]]
 
@@ -47,11 +61,11 @@ entry:
 
 ; CHECK: {{(bx lr|pop)}}
 
-; ARM_RW_SB: [[LCPI]]
-; ARM_RW_SB: .long   a(sbrel)
+; NO_MOVT_ARM_RW_SB: [[LCPI]]
+; NO_MOVT_ARM_RW_SB: .long   a(sbrel)
 
-; THUMB2_RW_SB: [[LCPI]]
-; THUMB2_RW_SB: .long   a(sbrel)
+; NO_MOVT_THUMB2_RW_SB: [[LCPI]]
+; NO_MOVT_THUMB2_RW_SB: .long   a(sbrel)
 
 ; THUMB1_RW_ABS: [[LCPI]]
 ; THUMB1_RW_ABS-NEXT: .long a
@@ -70,16 +84,24 @@ entry:
 ; 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]]]
+; ARM_RW_SB: movw    r[[REG:[0-9]]], :lower16:a
+; ARM_RW_SB: movt    r[[REG]], :upper16:a
+; ARM_RW_SB: str     r0, [r9, r[[REG:[0-9]]]]
+
+; NO_MOVT_ARM_RW_SB: ldr     r[[REG:[0-9]]], [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; NO_MOVT_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: movw    r[[REG:[0-9]]], :lower16:a(sbrel)
+; THUMB2_RW_SB: movt    r[[REG]], :upper16:a(sbrel)
 ; THUMB2_RW_SB: str.w   r0, [r9, r[[REG]]]
 
+; NO_MOVT_THUMB2_RW_SB: ldr     r[[REG:[0-9]]], [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; NO_MOVT_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]]]
 
@@ -89,11 +111,11 @@ entry:
 
 ; CHECK: {{(bx lr|pop)}}
 
-; ARM_RW_SB: [[LCPI]]
-; ARM_RW_SB: .long   a(sbrel)
+; NO_MOVT_ARM_RW_SB: [[LCPI]]
+; NO_MOVT_ARM_RW_SB: .long   a(sbrel)
 
-; THUMB2_RW_SB: [[LCPI]]
-; THUMB2_RW_SB: .long   a(sbrel)
+; NO_MOVT_THUMB2_RW_SB: [[LCPI]]
+; NO_MOVT_THUMB2_RW_SB: .long   a(sbrel)
 
 ; THUMB1_RW_ABS: [[LCPI]]
 ; THUMB1_RW_ABS-NEXT: .long a
@@ -112,21 +134,37 @@ entry:
 ; ARM_RO_ABS: movt    r[[reg]], :upper16:b
 ; ARM_RO_ABS: ldr     r0, [r[[reg]]]
 
+; NO_MOVT_ARM_RO_ABS: ldr     r[[REG:[0-9]]], [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; NO_MOVT_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]]]
 
+; NO_MOVT_ARM_RO_PC: ldr     r[[REG:[0-9]]], [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; NO_MOVT_ARM_RO_PC: [[LPC:.LPC[0-9]+_[0-9]+]]:
+; NO_MOVT_ARM_RO_PC: 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]]]
 
+; NO_MOVT_THUMB2_RO_ABS: ldr     r[[REG:[0-9]]], [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; NO_MOVT_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]]]
 
+; NO_MOVT_THUMB2_RO_PC: ldr     r[[REG:[0-9]]], [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; NO_MOVT_THUMB2_RO_PC: [[LPC:.LPC[0-9]+_[0-9]+]]:
+; NO_MOVT_THUMB2_RO_PC-NEXT: add     r[[REG]], pc
+; NO_MOVT_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]]]
 
@@ -137,9 +175,21 @@ entry:
 
 ; CHECK: {{(bx lr|pop)}}
 
+; NO_MOVT_ARM_RO_ABS: [[LCPI]]
+; NO_MOVT_ARM_RO_ABS-NEXT: .long b
+
+; NO_MOVT_THUMB2_RO_ABS: [[LCPI]]
+; NO_MOVT_THUMB2_RO_ABS-NEXT: .long b
+
 ; THUMB1_RO_ABS: [[LCPI]]
 ; THUMB1_RO_ABS-NEXT: .long b
 
+; NO_MOVT_ARM_RO_PC: [[LCPI]]
+; NO_MOVT_ARM_RO_PC-NEXT: .long b-([[LPC]]+8)
+
+; NO_MOVT_THUMB2_RO_PC: [[LCPI]]
+; NO_MOVT_THUMB2_RO_PC-NEXT: .long b-([[LPC]]+4)
+
 ; THUMB1_RO_PC: [[LCPI]]
 ; THUMB1_RO_PC-NEXT: .long b-([[LPC]]+4)
 }
@@ -152,15 +202,23 @@ entry:
 ; 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: movw    r[[REG:[0-9]]], :lower16:a(sbrel)
+; ARM_RW_SB: movt    r[[REG]], :upper16:a(sbrel)
 ; ARM_RW_SB: add     r0, r9, r[[REG]]
 
+; NO_MOVT_ARM_RW_SB: ldr     r[[REG:[0-9]]], [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; NO_MOVT_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: movw    r[[REG:[0-9]]], :lower16:a(sbrel)
+; THUMB2_RW_SB: movt    r[[REG]], :upper16:a(sbrel)
 ; THUMB2_RW_SB: add     r0, r9
 
+; NO_MOVT_THUMB2_RW_SB: ldr     r0, [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; NO_MOVT_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]+]]
@@ -169,11 +227,11 @@ entry:
 
 ; CHECK: {{(bx lr|pop)}}
 
-; ARM_RW_SB: [[LCPI]]
-; ARM_RW_SB: .long   a(sbrel)
+; NO_MOVT_ARM_RW_SB: [[LCPI]]
+; NO_MOVT_ARM_RW_SB: .long   a(sbrel)
 
-; THUMB2_RW_SB: [[LCPI]]
-; THUMB2_RW_SB: .long   a(sbrel)
+; NO_MOVT_THUMB2_RW_SB: [[LCPI]]
+; NO_MOVT_THUMB2_RW_SB: .long   a(sbrel)
 
 ; THUMB1_RW_ABS: [[LCPI]]
 ; THUMB1_RW_ABS-NEXT: .long a
@@ -190,19 +248,31 @@ entry:
 ; ARM_RO_ABS: movw    r[[REG:[0-9]]], :lower16:b
 ; ARM_RO_ABS: movt    r[[REG]], :upper16:b
 
+; NO_MOVT_ARM_RO_ABS: ldr     r0, [[LCPI:.LCPI[0-9]+_[0-9]+]]
+
 ; 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]]]
 
+; NO_MOVT_ARM_RO_PC: ldr     r[[REG:[0-9]]], [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; NO_MOVT_ARM_RO_PC: [[LPC:.LPC[0-9]+_[0-9]+]]:
+; NO_MOVT_ARM_RO_PC-NEXT: add     r0, pc, r[[REG]]
+
 ; THUMB2_RO_ABS: movw    r[[REG:[0-9]]], :lower16:b
 ; THUMB2_RO_ABS: movt    r[[REG]], :upper16:b
 
+; NO_MOVT_THUMB2_RO_ABS: ldr     r0, [[LCPI:.LCPI[0-9]+_[0-9]+]]
+
 ; 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
 
+; NO_MOVT_THUMB2_RO_PC: ldr     r[[REG:[0-9]]], [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; NO_MOVT_THUMB2_RO_PC: [[LPC:.LPC[0-9]+_[0-9]+]]:
+; NO_MOVT_THUMB2_RO_PC-NEXT: add     r[[REG]], 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]+]]
@@ -211,9 +281,21 @@ entry:
 
 ; CHECK: {{(bx lr|pop)}}
 
+; NO_MOVT_ARM_RO_ABS: [[LCPI]]
+; NO_MOVT_ARM_RO_ABS-NEXT: .long b
+
+; NO_MOVT_THUMB2_RO_ABS: [[LCPI]]
+; NO_MOVT_THUMB2_RO_ABS-NEXT: .long b
+
 ; THUMB1_RO_ABS: [[LCPI]]
 ; THUMB1_RO_ABS-NEXT: .long b
 
+; NO_MOVT_ARM_RO_PC: [[LCPI]]
+; NO_MOVT_ARM_RO_PC-NEXT: .long b-([[LPC]]+8)
+
+; NO_MOVT_THUMB2_RO_PC: [[LCPI]]
+; NO_MOVT_THUMB2_RO_PC-NEXT: .long b-([[LPC]]+4)
+
 ; THUMB1_RO_PC: [[LCPI]]
 ; THUMB1_RO_PC-NEXT: .long b-([[LPC]]+4)
 }
@@ -226,19 +308,31 @@ entry:
 ; ARM_RO_ABS: movw    r[[REG:[0-9]]], :lower16:take_addr_func
 ; ARM_RO_ABS: movt    r[[REG]], :upper16:take_addr_func
 
+; NO_MOVT_ARM_RO_ABS: ldr     r0, [[LCPI:.LCPI[0-9]+_[0-9]+]]
+
 ; 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]]]
 
+; NO_MOVT_ARM_RO_PC: ldr     r[[REG:[0-9]]], [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; NO_MOVT_ARM_RO_PC: [[LPC:.LPC[0-9]+_[0-9]+]]:
+; NO_MOVT_ARM_RO_PC-NEXT: add     r0, pc, r[[REG]]
+
 ; THUMB2_RO_ABS: movw    r[[REG:[0-9]]], :lower16:take_addr_func
 ; THUMB2_RO_ABS: movt    r[[REG]], :upper16:take_addr_func
 
+; NO_MOVT_THUMB2_RO_ABS: ldr     r0, [[LCPI:.LCPI[0-9]+_[0-9]+]]
+
 ; 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
 
+; NO_MOVT_THUMB2_RO_PC: ldr     r[[REG:[0-9]]], [[LCPI:.LCPI[0-9]+_[0-9]+]]
+; NO_MOVT_THUMB2_RO_PC: [[LPC:.LPC[0-9]+_[0-9]+]]:
+; NO_MOVT_THUMB2_RO_PC-NEXT: add     r[[REG]], 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]+]]
@@ -247,9 +341,21 @@ entry:
 
 ; CHECK: {{(bx lr|pop)}}
 
+; NO_MOVT_ARM_RO_ABS: [[LCPI]]
+; NO_MOVT_ARM_RO_ABS-NEXT: .long take_addr_func
+
+; NO_MOVT_THUMB2_RO_ABS: [[LCPI]]
+; NO_MOVT_THUMB2_RO_ABS-NEXT: .long take_addr_func
+
 ; THUMB1_RO_ABS: [[LCPI]]
 ; THUMB1_RO_ABS-NEXT: .long take_addr_func
 
+; NO_MOVT_ARM_RO_PC: [[LCPI]]
+; NO_MOVT_ARM_RO_PC-NEXT: .long take_addr_func-([[LPC]]+8)
+
+; NO_MOVT_THUMB2_RO_PC: [[LCPI]]
+; NO_MOVT_THUMB2_RO_PC-NEXT: .long take_addr_func-([[LPC]]+4)
+
 ; THUMB1_RO_PC: [[LCPI]]
 ; THUMB1_RO_PC-NEXT: .long take_addr_func-([[LPC]]+4)
 }