[llvm] r175257 - AArch64: refactor frame handling to use movz/movk for overlarge offsets.

Tim Northover Tim.Northover at arm.com
Fri Feb 15 01:33:27 PST 2013


Author: tnorthover
Date: Fri Feb 15 03:33:26 2013
New Revision: 175257

URL: http://llvm.org/viewvc/llvm-project?rev=175257&view=rev
Log:
AArch64: refactor frame handling to use movz/movk for overlarge offsets.

In the near future litpools will be in a different section, which means that
any access to them is at least two instructions. This makes the case for a
movz/movk pair (if total offset <= 32-bits) even more compelling.

Modified:
    llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.cpp
    llvm/trunk/test/CodeGen/AArch64/large-frame.ll

Modified: llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.cpp?rev=175257&r1=175256&r2=175257&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.cpp (original)
+++ llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.cpp Fri Feb 15 03:33:26 2013
@@ -623,18 +623,35 @@ void llvm::emitRegUpdate(MachineBasicBlo
   else if (abs(NumBytes) & ~0xffffff) {
     // Generically, we have to materialize the offset into a temporary register
     // and subtract it. There are a couple of ways this could be done, for now
-    // we'll go for a literal-pool load.
-    MachineFunction &MF = *MBB.getParent();
-    MachineConstantPool *MCP = MF.getConstantPool();
-    const Constant *C
-      = ConstantInt::get(Type::getInt64Ty(MF.getFunction()->getContext()),
-                         abs(NumBytes));
-    unsigned CPI = MCP->getConstantPoolIndex(C, 8);
+    // we'll use a movz/movk or movn/movk sequence.
+    uint64_t Bits = static_cast<uint64_t>(abs(NumBytes));
+    BuildMI(MBB, MBBI, dl, TII.get(AArch64::MOVZxii), ScratchReg)
+      .addImm(0xffff & Bits).addImm(0)
+      .setMIFlags(MIFlags);
 
-    // LDR xTMP, .LITPOOL
-    BuildMI(MBB, MBBI, dl, TII.get(AArch64::LDRx_lit), ScratchReg)
-      .addConstantPoolIndex(CPI)
-      .setMIFlag(MIFlags);
+    Bits >>= 16;
+    if (Bits & 0xffff) {
+      BuildMI(MBB, MBBI, dl, TII.get(AArch64::MOVKxii), ScratchReg)
+        .addReg(ScratchReg)
+        .addImm(0xffff & Bits).addImm(1)
+        .setMIFlags(MIFlags);
+    }
+
+    Bits >>= 16;
+    if (Bits & 0xffff) {
+      BuildMI(MBB, MBBI, dl, TII.get(AArch64::MOVKxii), ScratchReg)
+        .addReg(ScratchReg)
+        .addImm(0xffff & Bits).addImm(2)
+        .setMIFlags(MIFlags);
+    }
+
+    Bits >>= 16;
+    if (Bits & 0xffff) {
+      BuildMI(MBB, MBBI, dl, TII.get(AArch64::MOVKxii), ScratchReg)
+        .addReg(ScratchReg)
+        .addImm(0xffff & Bits).addImm(3)
+        .setMIFlags(MIFlags);
+    }
 
     // ADD DST, SRC, xTMP (, lsl #0)
     unsigned AddOp = NumBytes > 0 ? AArch64::ADDxxx_uxtx : AArch64::SUBxxx_uxtx;

Modified: llvm/trunk/test/CodeGen/AArch64/large-frame.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/large-frame.ll?rev=175257&r1=175256&r2=175257&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/large-frame.ll (original)
+++ llvm/trunk/test/CodeGen/AArch64/large-frame.ll Fri Feb 15 03:33:26 2013
@@ -11,17 +11,22 @@ define void @test_bigframe() {
   %var3 = alloca i8, i32 20000000
 ; CHECK: sub sp, sp, #496
 ; CHECK: str x30, [sp, #488]
-; CHECK: ldr [[FRAMEOFFSET:x[0-9]+]], [[FRAMEOFFSET_CPI:.LCPI0_[0-9]+]]
-; CHECK: sub sp, sp, [[FRAMEOFFSET]]
-
-; CHECK: ldr [[VAR1OFFSET:x[0-9]+]], [[VAR1LOC_CPI:.LCPI0_[0-9]+]]
+  ; Total adjust is 39999536
+; CHECK: movz [[SUBCONST:x[0-9]+]], #22576
+; CHECK: movk [[SUBCONST]], #610, lsl #16
+; CHECK: sub sp, sp, [[SUBCONST]]
+
+  ; Total offset is 20000024
+; CHECK: movz [[VAR1OFFSET:x[0-9]+]], #11544
+; CHECK: movk [[VAR1OFFSET]], #305, lsl #16
 ; CHECK: add {{x[0-9]+}}, sp, [[VAR1OFFSET]]
   store volatile i8* %var1, i8** @addr
 
   %var1plus2 = getelementptr i8* %var1, i32 2
   store volatile i8* %var1plus2, i8** @addr
 
-; CHECK: ldr [[VAR2OFFSET:x[0-9]+]], [[VAR2LOC_CPI:.LCPI0_[0-9]+]]
+; CHECK: movz [[VAR2OFFSET:x[0-9]+]], #11528
+; CHECK: movk [[VAR2OFFSET]], #305, lsl #16
 ; CHECK: add {{x[0-9]+}}, sp, [[VAR2OFFSET]]
   store volatile i8* %var2, i8** @addr
 
@@ -33,18 +38,10 @@ define void @test_bigframe() {
   %var3plus2 = getelementptr i8* %var3, i32 2
   store volatile i8* %var3plus2, i8** @addr
 
-; CHECK: ldr [[FRAMEOFFSET:x[0-9]+]], [[FRAMEOFFSET_CPI]]
-; CHECK: add sp, sp, [[FRAMEOFFSET]]
+; CHECK: movz [[ADDCONST:x[0-9]+]], #22576
+; CHECK: movk [[ADDCONST]], #610, lsl #16
+; CHECK: add sp, sp, [[ADDCONST]]
   ret void
-
-; CHECK: [[FRAMEOFFSET_CPI]]:
-; CHECK-NEXT: 39999536
-
-; CHECK: [[VAR1LOC_CPI]]:
-; CHECK-NEXT: 20000024
-
-; CHECK: [[VAR2LOC_CPI]]:
-; CHECK-NEXT: 20000008
 }
 
 define void @test_mediumframe() {
@@ -103,10 +100,10 @@ define void @test_tempallocation([8 x i6
 ; CHECK-NEXT: stp x19, x20, [sp,
 
 ; Make sure we don't trash an argument register
-; CHECK-NOT: ldr {{x[0-7]}}, .LCPI1
+; CHECK-NOT: movz {{x[0-7],}}
 ; CHECK: sub sp, sp,
 
-; CHECK-NOT: ldr {{x[0-7]}}, .LCPI1
+; CHECK-NOT: movz {{x[0-7],}}
 
 ; CHECK: bl use_addr
   call void @use_addr(i8* %var)





More information about the llvm-commits mailing list