[llvm] r312521 - [ARM] GlobalISel: Support global variables for RWPI

Diana Picus via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 5 00:57:41 PDT 2017


Author: rovka
Date: Tue Sep  5 00:57:41 2017
New Revision: 312521

URL: http://llvm.org/viewvc/llvm-project?rev=312521&view=rev
Log:
[ARM] GlobalISel: Support global variables for RWPI

In RWPI code, globals that are not read-only are accessed relative to
the SB register (R9). This is achieved by explicitly generating an ADD
instruction between SB and an offset that we either load from a constant
pool or movw + movt into a register.

Modified:
    llvm/trunk/lib/Target/ARM/ARMInstructionSelector.cpp
    llvm/trunk/test/CodeGen/ARM/GlobalISel/arm-isel-globals-ropi-rwpi.ll
    llvm/trunk/test/CodeGen/ARM/GlobalISel/arm-select-globals-ropi-rwpi.mir
    llvm/trunk/test/CodeGen/ARM/GlobalISel/arm-unsupported.ll

Modified: llvm/trunk/lib/Target/ARM/ARMInstructionSelector.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstructionSelector.cpp?rev=312521&r1=312520&r2=312521&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMInstructionSelector.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMInstructionSelector.cpp Tue Sep  5 00:57:41 2017
@@ -488,13 +488,8 @@ bool ARMInstructionSelector::insertCompa
 
 bool ARMInstructionSelector::selectGlobal(MachineInstrBuilder &MIB,
                                           MachineRegisterInfo &MRI) const {
-  if (TII.getSubtarget().isRWPI()) {
-    DEBUG(dbgs() << "RWPI not supported yet\n");
-    return false;
-  }
-
-  if (STI.isROPI() && !STI.isTargetELF()) {
-    DEBUG(dbgs() << "ROPI only supported for ELF\n");
+  if ((STI.isROPI() || STI.isRWPI()) && !STI.isTargetELF()) {
+    DEBUG(dbgs() << "ROPI and RWPI only supported for ELF\n");
     return false;
   }
 
@@ -510,7 +505,29 @@ bool ARMInstructionSelector::selectGloba
   auto ObjectFormat = TII.getSubtarget().getTargetTriple().getObjectFormat();
   bool UseMovt = TII.getSubtarget().useMovt(MF);
 
+  unsigned Size = TM.getPointerSize();
   unsigned Alignment = 4;
+
+  auto addOpsForConstantPoolLoad = [&MF, Alignment,
+                                    Size](MachineInstrBuilder &MIB,
+                                          const GlobalValue *GV, bool IsSBREL) {
+    assert(MIB->getOpcode() == ARM::LDRi12 && "Unsupported instruction");
+    auto ConstPool = MF.getConstantPool();
+    auto CPIndex =
+        // For SB relative entries we need a target-specific constant pool.
+        // Otherwise, just use a regular constant pool entry.
+        IsSBREL
+            ? ConstPool->getConstantPoolIndex(
+                  ARMConstantPoolConstant::Create(GV, ARMCP::SBREL), Alignment)
+            : ConstPool->getConstantPoolIndex(GV, Alignment);
+    MIB.addConstantPoolIndex(CPIndex, /*Offset*/ 0, /*TargetFlags*/ 0)
+        .addMemOperand(
+            MF.getMachineMemOperand(MachinePointerInfo::getConstantPool(MF),
+                                    MachineMemOperand::MOLoad, Size, Alignment))
+        .addImm(0)
+        .add(predOps(ARMCC::AL));
+  };
+
   if (TM.isPositionIndependent()) {
     bool Indirect = TII.getSubtarget().isGVIndirectSymbol(GV);
     // FIXME: Taking advantage of MOVT for ELF is pretty involved, so we don't
@@ -538,6 +555,32 @@ bool ARMInstructionSelector::selectGloba
     MIB->setDesc(TII.get(Opc));
     return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
   }
+  if (STI.isRWPI() && !isReadOnly) {
+    auto Offset = MRI.createVirtualRegister(&ARM::GPRRegClass);
+    MachineInstrBuilder OffsetMIB;
+    if (UseMovt) {
+      OffsetMIB = BuildMI(MBB, *MIB, MIB->getDebugLoc(),
+                          TII.get(ARM::MOVi32imm), Offset);
+      OffsetMIB.addGlobalAddress(GV, /*Offset*/ 0, ARMII::MO_SBREL);
+    } else {
+      // Load the offset from the constant pool.
+      OffsetMIB =
+          BuildMI(MBB, *MIB, MIB->getDebugLoc(), TII.get(ARM::LDRi12), Offset);
+      addOpsForConstantPoolLoad(OffsetMIB, GV, /*IsSBREL*/ true);
+    }
+    if (!constrainSelectedInstRegOperands(*OffsetMIB, TII, TRI, RBI))
+      return false;
+
+    // Add the offset to the SB register.
+    MIB->setDesc(TII.get(ARM::ADDrr));
+    MIB->RemoveOperand(1);
+    MIB.addReg(ARM::R9) // FIXME: don't hardcode R9
+        .addReg(Offset)
+        .add(predOps(ARMCC::AL))
+        .add(condCodeOp());
+
+    return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
+  }
 
   if (ObjectFormat == Triple::ELF) {
     if (UseMovt) {
@@ -546,14 +589,7 @@ bool ARMInstructionSelector::selectGloba
       // Load the global's address from the constant pool.
       MIB->setDesc(TII.get(ARM::LDRi12));
       MIB->RemoveOperand(1);
-      MIB.addConstantPoolIndex(
-             MF.getConstantPool()->getConstantPoolIndex(GV, Alignment),
-             /* Offset */ 0, /* TargetFlags */ 0)
-          .addMemOperand(MF.getMachineMemOperand(
-              MachinePointerInfo::getConstantPool(MF),
-              MachineMemOperand::MOLoad, TM.getPointerSize(), Alignment))
-          .addImm(0)
-          .add(predOps(ARMCC::AL));
+      addOpsForConstantPoolLoad(MIB, GV, /*IsSBREL*/ false);
     }
   } else if (ObjectFormat == Triple::MachO) {
     if (UseMovt)

Modified: llvm/trunk/test/CodeGen/ARM/GlobalISel/arm-isel-globals-ropi-rwpi.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/GlobalISel/arm-isel-globals-ropi-rwpi.ll?rev=312521&r1=312520&r2=312521&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/GlobalISel/arm-isel-globals-ropi-rwpi.ll (original)
+++ llvm/trunk/test/CodeGen/ARM/GlobalISel/arm-isel-globals-ropi-rwpi.ll Tue Sep  5 00:57:41 2017
@@ -1,5 +1,9 @@
 ; RUN: llc -mtriple armv7-linux -relocation-model=ropi -mattr=-no-movt,+v8m -global-isel %s -o - | FileCheck %s -check-prefixes=CHECK,RW-DEFAULT-MOVT,RW-DEFAULT,ROPI-MOVT,ROPI
 ; RUN: llc -mtriple armv7-linux -relocation-model=ropi -mattr=+no-movt -global-isel %s -o - | FileCheck %s -check-prefixes=CHECK,RW-DEFAULT-NOMOVT,RW-DEFAULT,ROPI-NOMOVT,ROPI
+; RUN: llc -mtriple armv7-linux -relocation-model=rwpi -mattr=-no-movt,+v8m -global-isel %s -o - | FileCheck %s -check-prefixes=CHECK,RO-DEFAULT-MOVT,RO-DEFAULT,RWPI-MOVT,RWPI
+; RUN: llc -mtriple armv7-linux -relocation-model=rwpi -mattr=+no-movt -global-isel %s -o - | FileCheck %s -check-prefixes=CHECK,RO-DEFAULT-NOMOVT,RO-DEFAULT,RWPI-NOMOVT,RWPI
+; RUN: llc -mtriple armv7-linux -relocation-model=ropi-rwpi -mattr=-no-movt,+v8m -global-isel %s -o - | FileCheck %s -check-prefixes=CHECK,ROPI-MOVT,ROPI,RWPI-MOVT,RWPI
+; RUN: llc -mtriple armv7-linux -relocation-model=ropi-rwpi -mattr=+no-movt -global-isel %s -o - | FileCheck %s -check-prefixes=CHECK,ROPI-NOMOVT,ROPI,RWPI-NOMOVT,RWPI
 
 @internal_global = internal global i32 42
 define i32 @test_internal_global() {
@@ -11,6 +15,15 @@ define i32 @test_internal_global() {
 ; RW-DEFAULT-NEXT: bx lr
 ; RW-DEFAULT-NOMOVT: [[LABEL]]:
 ; RW-DEFAULT-NOMOVT-NEXT: .long internal_global
+
+; RWPI-MOVT: movw [[OFFSET:r[0-9]+]], :lower16:internal_global(sbrel)
+; RWPI-MOVT-NEXT: movt [[OFFSET]], :upper16:internal_global(sbrel)
+; RWPI-NOMOVT: ldr [[OFFSET:r[0-9]+]], [[LABEL:.L[[:alnum:]_]+]]
+; RWPI-NEXT: add r[[ADDR:[0-9]+]], r9, [[OFFSET]]
+; RWPI-NEXT: ldr r0, [r[[ADDR]]]
+; RWPI-NEXT: bx lr
+; RWPI-NOMOVT: [[LABEL]]:
+; RWPI-NOMOVT-NEXT: .long internal_global(sbrel)
 entry:
   %v = load i32, i32* @internal_global
   ret i32 %v
@@ -26,6 +39,15 @@ define i32 @test_external_global() {
 ; RW-DEFAULT-NEXT: bx lr
 ; RW-DEFAULT-NOMOVT: [[LABEL]]:
 ; RW-DEFAULT-NOMOVT: .long external_global
+
+; RWPI-MOVT: movw [[OFFSET:r[0-9]+]], :lower16:external_global(sbrel)
+; RWPI-MOVT-NEXT: movt [[OFFSET]], :upper16:external_global(sbrel)
+; RWPI-NOMOVT: ldr [[OFFSET:r[0-9]+]], [[LABEL:.L[[:alnum:]_]+]]
+; RWPI-NEXT: add r[[ADDR:[0-9]+]], r9, [[OFFSET]]
+; RWPI-NEXT: ldr r0, [r[[ADDR]]]
+; RWPI-NEXT: bx lr
+; RWPI-NOMOVT: [[LABEL]]:
+; RWPI-NOMOVT-NEXT: .long external_global(sbrel)
 entry:
   %v = load i32, i32* @external_global
   ret i32 %v
@@ -44,6 +66,14 @@ define i32 @test_internal_constant() {
 ; ROPI-NEXT: bx lr
 ; ROPI-NOMOVT: [[LABEL]]:
 ; ROPI-NOMOVT-NEXT: .long internal_constant-([[ANCHOR]]+8)
+
+; RO-DEFAULT-MOVT: movw r[[ADDR:[0-9]+]], :lower16:internal_constant
+; RO-DEFAULT-MOVT-NEXT: movt r[[ADDR]], :upper16:internal_constant
+; RO-DEFAULT-NOMOVT: ldr r[[ADDR:[0-9]+]], [[LABEL:.L[[:alnum:]_]+]]
+; RO-DEFAULT-NEXT: ldr r0, [r[[ADDR]]]
+; RO-DEFAULT-NEXT: bx lr
+; RO-DEFAULT-NOMOVT: [[LABEL]]:
+; RO-DEFAULT-NOMOVT-NEXT: .long internal_constant
 entry:
   %v = load i32, i32* @internal_constant
   ret i32 %v
@@ -62,6 +92,14 @@ define i32 @test_external_constant() {
 ; ROPI-NEXT: bx lr
 ; ROPI-NOMOVT: [[LABEL]]:
 ; ROPI-NOMOVT-NEXT: .long external_constant-([[ANCHOR]]+8)
+
+; RO-DEFAULT-MOVT: movw r[[ADDR:[0-9]+]], :lower16:external_constant
+; RO-DEFAULT-MOVT-NEXT: movt r[[ADDR]], :upper16:external_constant
+; RO-DEFAULT-NOMOVT: ldr r[[ADDR:[0-9]+]], [[LABEL:.L[[:alnum:]_]+]]
+; RO-DEFAULT-NEXT: ldr r0, [r[[ADDR]]]
+; RO-DEFAULT-NEXT: bx lr
+; RO-DEFAULT-NOMOVT: [[LABEL]]:
+; RO-DEFAULT-NOMOVT: .long external_constant
 entry:
   %v = load i32, i32* @external_constant
   ret i32 %v
@@ -71,6 +109,14 @@ entry:
 ; RW-DEFAULT-NOMOVT: .long 42
 ; RW-DEFAULT-NOMOVT: .size internal_global, 4
 
+; RWPI-NOMOVT: internal_global:
+; RWPI-NOMOVT: .long 42
+; RWPI-NOMOVT: .size internal_global, 4
+
 ; ROPI-NOMOVT: internal_constant:
 ; ROPI-NOMOVT: .long 42
 ; ROPI-NOMOVT: .size internal_constant, 4
+
+; RO-DEFAULT-NOMOVT: internal_constant:
+; RO-DEFAULT-NOMOVT: .long 42
+; RO-DEFAULT-NOMOVT: .size internal_constant, 4

Modified: llvm/trunk/test/CodeGen/ARM/GlobalISel/arm-select-globals-ropi-rwpi.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/GlobalISel/arm-select-globals-ropi-rwpi.mir?rev=312521&r1=312520&r2=312521&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/GlobalISel/arm-select-globals-ropi-rwpi.mir (original)
+++ llvm/trunk/test/CodeGen/ARM/GlobalISel/arm-select-globals-ropi-rwpi.mir Tue Sep  5 00:57:41 2017
@@ -1,5 +1,9 @@
 # RUN: llc -O0 -mtriple arm-linux -relocation-model=ropi -mattr=-no-movt,+v8m -global-isel -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=CHECK,RW-DEFAULT-MOVT,RW-DEFAULT,ROPI-MOVT,ROPI
 # RUN: llc -O0 -mtriple arm-linux -relocation-model=ropi -mattr=+no-movt -global-isel -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=CHECK,RW-DEFAULT-NOMOVT,RW-DEFAULT,ROPI-NOMOVT,ROPI
+# RUN: llc -O0 -mtriple arm-linux -relocation-model=rwpi -mattr=-no-movt,+v8m -global-isel -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=CHECK,RWPI-MOVT,RWPI,RO-DEFAULT-MOVT,RO-DEFAULT
+# RUN: llc -O0 -mtriple arm-linux -relocation-model=rwpi -mattr=+no-movt -global-isel -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=CHECK,RWPI-NOMOVT,RWPI,RO-DEFAULT-NOMOVT,RO-DEFAULT
+# RUN: llc -O0 -mtriple arm-linux -relocation-model=ropi-rwpi -mattr=-no-movt,+v8m -global-isel -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=CHECK,RWPI-MOVT,RWPI,ROPI-MOVT,ROPI
+# RUN: llc -O0 -mtriple arm-linux -relocation-model=ropi-rwpi -mattr=+no-movt -global-isel -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=CHECK,RWPI-NOMOVT,RWPI,ROPI-NOMOVT,ROPI
 --- |
   @internal_global = internal global i32 42
   define void @test_internal_global() { ret void }
@@ -26,11 +30,17 @@ registers:
 # RW-DEFAULT-NOMOVT: constants:
 # RW-DEFAULT-NOMOVT: id: 0
 # RW-DEFAULT-NOMOVT: value: 'i32* @internal_global'
+# RWPI-NOMOVT: constants:
+# RWPI-NOMOVT: id: 0
+# RWPI-NOMOVT: value: 'internal_global(SBREL)'
 body:             |
   bb.0:
     %0(p0) = G_GLOBAL_VALUE @internal_global
     ; RW-DEFAULT-MOVT: [[G:%[0-9]+]] = MOVi32imm @internal_global
     ; RW-DEFAULT-NOMOVT: [[G:%[0-9]+]] = LDRi12 %const.0, 0, 14, _ :: (load 4 from constant-pool)
+    ; RWPI-MOVT: [[OFF:%[0-9]+]] = MOVi32imm {{.*}} @internal_global
+    ; RWPI-NOMOVT: [[OFF:%[0-9]+]] = LDRi12 %const.0, 0, 14, _ :: (load 4 from constant-pool)
+    ; RWPI: [[G:%[0-9]+]] = ADDrr %r9, [[OFF]], 14, _, _
 
     %1(s32) = G_LOAD %0(p0) :: (load 4 from @internal_global)
     ; CHECK: [[V:%[0-9]+]] = LDRi12 [[G]], 0, 14, _ :: (load 4 from @internal_global)
@@ -54,11 +64,17 @@ registers:
 # RW-DEFAULT-NOMOVT: constants:
 # RW-DEFAULT-NOMOVT: id: 0
 # RW-DEFAULT-NOMOVT: value: 'i32* @external_global'
+# RWPI-NOMOVT: constants:
+# RWPI-NOMOVT: id: 0
+# RWPI-NOMOVT: value: 'external_global(SBREL)'
 body:             |
   bb.0:
     %0(p0) = G_GLOBAL_VALUE @external_global
     ; RW-DEFAULT-MOVT: [[G:%[0-9]+]] = MOVi32imm @external_global
     ; RW-DEFAULT-NOMOVT: [[G:%[0-9]+]] = LDRi12 %const.0, 0, 14, _ :: (load 4 from constant-pool)
+    ; RWPI-MOVT: [[OFF:%[0-9]+]] = MOVi32imm {{.*}} @external_global
+    ; RWPI-NOMOVT: [[OFF:%[0-9]+]] = LDRi12 %const.0, 0, 14, _ :: (load 4 from constant-pool)
+    ; RWPI: [[G:%[0-9]+]] = ADDrr %r9, [[OFF]], 14, _, _
 
     %1(s32) = G_LOAD %0(p0) :: (load 4 from @external_global)
     ; CHECK: [[V:%[0-9]+]] = LDRi12 [[G]], 0, 14, _ :: (load 4 from @external_global)
@@ -79,11 +95,16 @@ selected:        false
 registers:
   - { id: 0, class: gprb }
   - { id: 1, class: gprb }
+# RO-DEFAULT-NOMOVT: constants:
+# RO-DEFAULT-NOMOVT: id: 0
+# RO-DEFAULT-NOMOVT: value: 'i32* @internal_constant'
 body:             |
   bb.0:
     %0(p0) = G_GLOBAL_VALUE @internal_constant
     ; ROPI-MOVT: [[G:%[0-9]+]] = MOV_ga_pcrel @internal_constant
     ; ROPI-NOMOVT: [[G:%[0-9]+]] = LDRLIT_ga_pcrel @internal_constant
+    ; RO-DEFAULT-MOVT: [[G:%[0-9]+]] = MOVi32imm @internal_constant
+    ; RO-DEFAULT-NOMOVT: [[G:%[0-9]+]] = LDRi12 %const.0, 0, 14, _ :: (load 4 from constant-pool)
 
     %1(s32) = G_LOAD %0(p0) :: (load 4 from @internal_constant)
     ; CHECK: [[V:%[0-9]+]] = LDRi12 [[G]], 0, 14, _ :: (load 4 from @internal_constant)
@@ -104,11 +125,16 @@ selected:        false
 registers:
   - { id: 0, class: gprb }
   - { id: 1, class: gprb }
+# RO-DEFAULT-NOMOVT: constants:
+# RO-DEFAULT-NOMOVT: id: 0
+# RO-DEFAULT-NOMOVT: value: 'i32* @external_constant'
 body:             |
   bb.0:
     %0(p0) = G_GLOBAL_VALUE @external_constant
     ; ROPI-MOVT: [[G:%[0-9]+]] = MOV_ga_pcrel @external_constant
     ; ROPI-NOMOVT: [[G:%[0-9]+]] = LDRLIT_ga_pcrel @external_constant
+    ; RO-DEFAULT-MOVT: [[G:%[0-9]+]] = MOVi32imm @external_constant
+    ; RO-DEFAULT-NOMOVT: [[G:%[0-9]+]] = LDRi12 %const.0, 0, 14, _ :: (load 4 from constant-pool)
 
     %1(s32) = G_LOAD %0(p0) :: (load 4 from @external_constant)
     ; CHECK: [[V:%[0-9]+]] = LDRi12 [[G]], 0, 14, _ :: (load 4 from @external_constant)

Modified: llvm/trunk/test/CodeGen/ARM/GlobalISel/arm-unsupported.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/GlobalISel/arm-unsupported.ll?rev=312521&r1=312520&r2=312521&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/GlobalISel/arm-unsupported.ll (original)
+++ llvm/trunk/test/CodeGen/ARM/GlobalISel/arm-unsupported.ll Tue Sep  5 00:57:41 2017
@@ -113,16 +113,4 @@ define i32 @test_thread_local_global() {
   ret i32 %v
 }
 
- at a_global = external global i32
-
-define i32 @test_global_reloc_models() {
-; This is only unsupported for the RWPI relocation modes.
-; RWPI: remark: {{.*}} cannot select: {{.*}} G_GLOBAL_VALUE
-; RWPI-LABEL: warning: Instruction selection used fallback path for test_global_reloc_models
-; ROPI-RWPI: remark: {{.*}} cannot select: {{.*}} G_GLOBAL_VALUE
-; ROPI-RWPI-LABEL: warning: Instruction selection used fallback path for test_global_reloc_models
-  %v = load i32, i32* @a_global
-  ret i32 %v
-}
-
 attributes #0 = { "target-features"="+thumb-mode" }




More information about the llvm-commits mailing list