]> granicus.if.org Git - llvm/commitdiff
[AArch64] Fix offset calculation
authorShoaib Meenai <smeenai@fb.com>
Wed, 16 Oct 2019 21:41:05 +0000 (21:41 +0000)
committerShoaib Meenai <smeenai@fb.com>
Wed, 16 Oct 2019 21:41:05 +0000 (21:41 +0000)
r374772 changed Offset to be an int64_t but left NewOffset as an int.
Scale is unsigned, so in the calculation `Offset - NewOffset * Scale`,
`NewOffset * Scale` was promoted to unsigned and was then zero-extended
to 64 bits, leading to an incorrect computation which manifested as an
out-of-memory when building the Swift standard library for Android
aarch64. Promote NewOffset to int64_t to fix this, and promote
EmittableOffset as well, since its one user passes it to a function
which takes an int64_t anyway.

Test case based on a suggestion by Sander de Smalen!

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

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

lib/Target/AArch64/AArch64InstrInfo.cpp
lib/Target/AArch64/AArch64InstrInfo.h
test/CodeGen/AArch64/framelayout-offset-immediate-change.mir [new file with mode: 0644]

index 895de9ac7b98716bb6a50f6f50f77ebdf3fc4064..5c35e5bcdd30e76daadbcedd7fab72eacd36d8cb 100644 (file)
@@ -3368,7 +3368,7 @@ int llvm::isAArch64FrameOffsetLegal(const MachineInstr &MI,
                                     StackOffset &SOffset,
                                     bool *OutUseUnscaledOp,
                                     unsigned *OutUnscaledOp,
-                                    int *EmittableOffset) {
+                                    int64_t *EmittableOffset) {
   // Set output values in case of early exit.
   if (EmittableOffset)
     *EmittableOffset = 0;
@@ -3430,7 +3430,7 @@ int llvm::isAArch64FrameOffsetLegal(const MachineInstr &MI,
          "Cannot have remainder when using unscaled op");
 
   assert(MinOff < MaxOff && "Unexpected Min/Max offsets");
-  int NewOffset = Offset / Scale;
+  int64_t NewOffset = Offset / Scale;
   if (MinOff <= NewOffset && NewOffset <= MaxOff)
     Offset = Remainder;
   else {
@@ -3471,7 +3471,7 @@ bool llvm::rewriteAArch64FrameIndex(MachineInstr &MI, unsigned FrameRegIdx,
     return true;
   }
 
-  int NewOffset;
+  int64_t NewOffset;
   unsigned UnscaledOp;
   bool UseUnscaledOp;
   int Status = isAArch64FrameOffsetLegal(MI, Offset, &UseUnscaledOp,
index 404acb9f898fd2ddbd76e998123a7911ce04adfd..1688045e4fb86cf5653eaa9cdcf01ed44cf22dc3 100644 (file)
@@ -335,7 +335,7 @@ enum AArch64FrameOffsetStatus {
 int isAArch64FrameOffsetLegal(const MachineInstr &MI, StackOffset &Offset,
                               bool *OutUseUnscaledOp = nullptr,
                               unsigned *OutUnscaledOp = nullptr,
-                              int *EmittableOffset = nullptr);
+                              int64_t *EmittableOffset = nullptr);
 
 static inline bool isUncondBranchOpcode(int Opc) { return Opc == AArch64::B; }
 
diff --git a/test/CodeGen/AArch64/framelayout-offset-immediate-change.mir b/test/CodeGen/AArch64/framelayout-offset-immediate-change.mir
new file mode 100644 (file)
index 0000000..59b04dd
--- /dev/null
@@ -0,0 +1,17 @@
+# RUN: llc -mtriple=aarch64-none-linux-gnu -run-pass=prologepilog %s -o - | FileCheck %s
+---
+name: framelayout_offset_immediate_change
+tracksRegLiveness: true
+fixedStack:
+  - { id: 0, offset: 0, size: 1}
+body: |
+  bb.0:
+    $x0 = LDURXi %fixed-stack.0, -264
+    RET_ReallyLR
+...
+# CHECK:      name:            framelayout_offset_immediate_change
+# CHECK:      body:             |
+# CHECK-NEXT:   bb.0:
+# CHECK-NEXT:     $x8 = SUBXri $sp, 8, 0
+# CHECK-NEXT:     $x0 = LDURXi killed $x8, -256
+# CHECK-NEXT:     RET_ReallyLR