Commit 52078d5b authored by Hans Wennborg's avatar Hans Wennborg
Browse files

Merging r278559:

------------------------------------------------------------------------
r278559 | efriedma | 2016-08-12 13:28:02 -0700 (Fri, 12 Aug 2016) | 7 lines

[AArch64LoadStoreOpt] Handle offsets correctly for post-indexed paired loads.

Trunk would try to create something like "stp x9, x8, [x0], #512", which isn't actually a valid instruction.

Differential revision: https://reviews.llvm.org/D23368


------------------------------------------------------------------------

llvm-svn: 279123
parent 5050823a
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -1427,9 +1427,6 @@ bool AArch64LoadStoreOpt::isMatchingUpdateInsn(MachineInstr &MemMI,
  default:
    break;
  case AArch64::SUBXri:
    // Negate the offset for a SUB instruction.
    Offset *= -1;
  // FALLTHROUGH
  case AArch64::ADDXri:
    // Make sure it's a vanilla immediate operand, not a relocation or
    // anything else we can't handle.
@@ -1447,6 +1444,9 @@ bool AArch64LoadStoreOpt::isMatchingUpdateInsn(MachineInstr &MemMI,

    bool IsPairedInsn = isPairedLdSt(MemMI);
    int UpdateOffset = MI.getOperand(2).getImm();
    if (MI.getOpcode() == AArch64::SUBXri)
      UpdateOffset = -UpdateOffset;

    // For non-paired load/store instructions, the immediate must fit in a
    // signed 9-bit integer.
    if (!IsPairedInsn && (UpdateOffset > 255 || UpdateOffset < -256))
@@ -1461,13 +1461,13 @@ bool AArch64LoadStoreOpt::isMatchingUpdateInsn(MachineInstr &MemMI,
        break;

      int ScaledOffset = UpdateOffset / Scale;
      if (ScaledOffset > 64 || ScaledOffset < -64)
      if (ScaledOffset > 63 || ScaledOffset < -64)
        break;
    }

    // If we have a non-zero Offset, we check that it matches the amount
    // we're adding to the register.
    if (!Offset || Offset == MI.getOperand(2).getImm())
    if (!Offset || Offset == UpdateOffset)
      return true;
    break;
  }
+102 −1
Original line number Diff line number Diff line
; RUN: llc -mtriple=aarch64-linux-gnu -aarch64-atomic-cfg-tidy=0 -verify-machineinstrs -o - %s | FileCheck %s
; RUN: llc -mtriple=aarch64-linux-gnu -aarch64-atomic-cfg-tidy=0 -disable-lsr -verify-machineinstrs -o - %s | FileCheck %s

; This file contains tests for the AArch64 load/store optimizer.

@@ -1232,3 +1232,104 @@ for.body:
end:
  ret void
}

define void @post-indexed-sub-doubleword-offset-min(i64* %a, i64* %b, i64 %count) nounwind {
; CHECK-LABEL: post-indexed-sub-doubleword-offset-min
; CHECK: ldr x{{[0-9]+}}, [x{{[0-9]+}}], #-256
; CHECK: str x{{[0-9]+}}, [x{{[0-9]+}}], #-256
  br label %for.body
for.body:
  %phi1 = phi i64* [ %gep4, %for.body ], [ %b, %0 ]
  %phi2 = phi i64* [ %gep3, %for.body ], [ %a, %0 ]
  %i = phi i64 [ %dec.i, %for.body], [ %count, %0 ]
  %gep1 = getelementptr i64, i64* %phi1, i64 1
  %load1 = load i64, i64* %gep1
  %gep2 = getelementptr i64, i64* %phi2, i64 1
  store i64 %load1, i64* %gep2
  %load2 = load i64, i64* %phi1
  store i64 %load2, i64* %phi2
  %dec.i = add nsw i64 %i, -1
  %gep3 = getelementptr i64, i64* %phi2, i64 -32
  %gep4 = getelementptr i64, i64* %phi1, i64 -32
  %cond = icmp sgt i64 %dec.i, 0
  br i1 %cond, label %for.body, label %end
end:
  ret void
}

define void @post-indexed-doubleword-offset-out-of-range(i64* %a, i64* %b, i64 %count) nounwind {
; CHECK-LABEL: post-indexed-doubleword-offset-out-of-range
; CHECK: ldr x{{[0-9]+}}, [x{{[0-9]+}}]
; CHECK: add x{{[0-9]+}}, x{{[0-9]+}}, #256
; CHECK: str x{{[0-9]+}}, [x{{[0-9]+}}]
; CHECK: add x{{[0-9]+}}, x{{[0-9]+}}, #256

  br label %for.body
for.body:
  %phi1 = phi i64* [ %gep4, %for.body ], [ %b, %0 ]
  %phi2 = phi i64* [ %gep3, %for.body ], [ %a, %0 ]
  %i = phi i64 [ %dec.i, %for.body], [ %count, %0 ]
  %gep1 = getelementptr i64, i64* %phi1, i64 1
  %load1 = load i64, i64* %gep1
  %gep2 = getelementptr i64, i64* %phi2, i64 1
  store i64 %load1, i64* %gep2
  %load2 = load i64, i64* %phi1
  store i64 %load2, i64* %phi2
  %dec.i = add nsw i64 %i, -1
  %gep3 = getelementptr i64, i64* %phi2, i64 32
  %gep4 = getelementptr i64, i64* %phi1, i64 32
  %cond = icmp sgt i64 %dec.i, 0
  br i1 %cond, label %for.body, label %end
end:
  ret void
}

define void @post-indexed-paired-min-offset(i64* %a, i64* %b, i64 %count) nounwind {
; CHECK-LABEL: post-indexed-paired-min-offset
; CHECK: ldp x{{[0-9]+}}, x{{[0-9]+}}, [x{{[0-9]+}}], #-512
; CHECK: stp x{{[0-9]+}}, x{{[0-9]+}}, [x{{[0-9]+}}], #-512
  br label %for.body
for.body:
  %phi1 = phi i64* [ %gep4, %for.body ], [ %b, %0 ]
  %phi2 = phi i64* [ %gep3, %for.body ], [ %a, %0 ]
  %i = phi i64 [ %dec.i, %for.body], [ %count, %0 ]
  %gep1 = getelementptr i64, i64* %phi1, i64 1
  %load1 = load i64, i64* %gep1
  %gep2 = getelementptr i64, i64* %phi2, i64 1
  %load2 = load i64, i64* %phi1
  store i64 %load1, i64* %gep2
  store i64 %load2, i64* %phi2
  %dec.i = add nsw i64 %i, -1
  %gep3 = getelementptr i64, i64* %phi2, i64 -64
  %gep4 = getelementptr i64, i64* %phi1, i64 -64
  %cond = icmp sgt i64 %dec.i, 0
  br i1 %cond, label %for.body, label %end
end:
  ret void
}

define void @post-indexed-paired-offset-out-of-range(i64* %a, i64* %b, i64 %count) nounwind {
; CHECK-LABEL: post-indexed-paired-offset-out-of-range
; CHECK: ldp x{{[0-9]+}}, x{{[0-9]+}}, [x{{[0-9]+}}]
; CHECK: add x{{[0-9]+}}, x{{[0-9]+}}, #512
; CHECK: stp x{{[0-9]+}}, x{{[0-9]+}}, [x{{[0-9]+}}]
; CHECK: add x{{[0-9]+}}, x{{[0-9]+}}, #512
  br label %for.body
for.body:
  %phi1 = phi i64* [ %gep4, %for.body ], [ %b, %0 ]
  %phi2 = phi i64* [ %gep3, %for.body ], [ %a, %0 ]
  %i = phi i64 [ %dec.i, %for.body], [ %count, %0 ]
  %gep1 = getelementptr i64, i64* %phi1, i64 1
  %load1 = load i64, i64* %phi1
  %gep2 = getelementptr i64, i64* %phi2, i64 1
  %load2 = load i64, i64* %gep1
  store i64 %load1, i64* %gep2
  store i64 %load2, i64* %phi2
  %dec.i = add nsw i64 %i, -1
  %gep3 = getelementptr i64, i64* %phi2, i64 64
  %gep4 = getelementptr i64, i64* %phi1, i64 64
  %cond = icmp sgt i64 %dec.i, 0
  br i1 %cond, label %for.body, label %end
end:
  ret void
}