; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3
; RUN: llc -mtriple=aarch64-apple-ios -verify-machineinstrs -global-isel -aarch64-enable-sink-fold=true -aarch64-postlegalizer-consecutive-memops=0 < %s | FileCheck %s --check-prefix=CHECK-NO-SPLIT
; RUN: llc -mtriple=aarch64-apple-ios -verify-machineinstrs -global-isel -aarch64-enable-sink-fold=true < %s | FileCheck %s --check-prefix=CHECK-SPLIT

define void @basic_split(ptr %p) {
; CHECK-NO-SPLIT-LABEL: basic_split:
; CHECK-NO-SPLIT:       ; %bb.0:
; CHECK-NO-SPLIT-NEXT:    str xzr, [x0, #8000]
; CHECK-NO-SPLIT-NEXT:    str xzr, [x0, #8008]
; CHECK-NO-SPLIT-NEXT:    str xzr, [x0, #8016]
; CHECK-NO-SPLIT-NEXT:    str xzr, [x0, #8024]
; CHECK-NO-SPLIT-NEXT:    str xzr, [x0, #8032]
; CHECK-NO-SPLIT-NEXT:    str xzr, [x0, #8040]
; CHECK-NO-SPLIT-NEXT:    ret
;
; CHECK-SPLIT-LABEL: basic_split:
; CHECK-SPLIT:       ; %bb.0:
; CHECK-SPLIT-NEXT:    mov w8, #8000 ; =0x1f40
; CHECK-SPLIT-NEXT:    add x8, x0, x8
; CHECK-SPLIT-NEXT:    stp xzr, xzr, [x8]
; CHECK-SPLIT-NEXT:    stp xzr, xzr, [x8, #16]
; CHECK-SPLIT-NEXT:    stp xzr, xzr, [x8, #32]
; CHECK-SPLIT-NEXT:    ret
  %bigoffset = getelementptr i64, ptr %p, i64 1000
  store i64 0, ptr %bigoffset
  %addr2 = getelementptr i64, ptr %p, i64 1001
  store i64 0, ptr %addr2
  %addr3 = getelementptr i64, ptr %p, i64 1002
  store i64 0, ptr %addr3
  %addr4 = getelementptr i64, ptr %p, i64 1003
  store i64 0, ptr %addr4
  %addr5 = getelementptr i64, ptr %p, i64 1004
  store i64 0, ptr %addr5
  %addr6 = getelementptr i64, ptr %p, i64 1005
  store i64 0, ptr %addr6
  ret void
}

define void @basic_multi_use_ptr(ptr %p, ptr %p2) {
; CHECK-NO-SPLIT-LABEL: basic_multi_use_ptr:
; CHECK-NO-SPLIT:       ; %bb.0:
; CHECK-NO-SPLIT-NEXT:    mov w8, #8008 ; =0x1f48
; CHECK-NO-SPLIT-NEXT:    str xzr, [x0, #8000]
; CHECK-NO-SPLIT-NEXT:    add x8, x0, x8
; CHECK-NO-SPLIT-NEXT:    str xzr, [x0, #8008]
; CHECK-NO-SPLIT-NEXT:    str xzr, [x0, #8016]
; CHECK-NO-SPLIT-NEXT:    str xzr, [x0, #8024]
; CHECK-NO-SPLIT-NEXT:    str x8, [x1]
; CHECK-NO-SPLIT-NEXT:    ret
;
; CHECK-SPLIT-LABEL: basic_multi_use_ptr:
; CHECK-SPLIT:       ; %bb.0:
; CHECK-SPLIT-NEXT:    mov w8, #8008 ; =0x1f48
; CHECK-SPLIT-NEXT:    str xzr, [x0, #8000]
; CHECK-SPLIT-NEXT:    add x8, x0, x8
; CHECK-SPLIT-NEXT:    str xzr, [x0, #8008]
; CHECK-SPLIT-NEXT:    str xzr, [x0, #8016]
; CHECK-SPLIT-NEXT:    str xzr, [x0, #8024]
; CHECK-SPLIT-NEXT:    str x8, [x1]
; CHECK-SPLIT-NEXT:    ret
  %bigoffset = getelementptr i64, ptr %p, i64 1000
  store i64 0, ptr %bigoffset
  %addr2 = getelementptr i64, ptr %p, i64 1001
  store i64 0, ptr %addr2
  %addr3 = getelementptr i64, ptr %p, i64 1002
  store i64 0, ptr %addr3
  %addr4 = getelementptr i64, ptr %p, i64 1003
  store i64 0, ptr %addr4
  ; multiuse of %addr2
  store ptr %addr2, ptr %p2
  ret void
}

define void @not_consecutive(ptr %p) {
; CHECK-NO-SPLIT-LABEL: not_consecutive:
; CHECK-NO-SPLIT:       ; %bb.0:
; CHECK-NO-SPLIT-NEXT:    str xzr, [x0, #8000]
; CHECK-NO-SPLIT-NEXT:    str xzr, [x0, #8008]
; CHECK-NO-SPLIT-NEXT:    str xzr, [x0, #8024]
; CHECK-NO-SPLIT-NEXT:    str xzr, [x0, #8032]
; CHECK-NO-SPLIT-NEXT:    ret
;
; CHECK-SPLIT-LABEL: not_consecutive:
; CHECK-SPLIT:       ; %bb.0:
; CHECK-SPLIT-NEXT:    str xzr, [x0, #8000]
; CHECK-SPLIT-NEXT:    str xzr, [x0, #8008]
; CHECK-SPLIT-NEXT:    str xzr, [x0, #8024]
; CHECK-SPLIT-NEXT:    str xzr, [x0, #8032]
; CHECK-SPLIT-NEXT:    ret
  %bigoffset = getelementptr i64, ptr %p, i64 1000
  store i64 0, ptr %bigoffset
  %addr2 = getelementptr i64, ptr %p, i64 1001
  store i64 0, ptr %addr2
  %addr3 = getelementptr i64, ptr %p, i64 1003
  store i64 0, ptr %addr3
  %addr4 = getelementptr i64, ptr %p, i64 1004
  store i64 0, ptr %addr4
  ret void
}

define void @early_store_is_invalid_but_split_rest(ptr %p) {
; CHECK-NO-SPLIT-LABEL: early_store_is_invalid_but_split_rest:
; CHECK-NO-SPLIT:       ; %bb.0:
; CHECK-NO-SPLIT-NEXT:    str xzr, [x0, #8000]
; CHECK-NO-SPLIT-NEXT:    str xzr, [x0, #8080]
; CHECK-NO-SPLIT-NEXT:    str xzr, [x0, #8016]
; CHECK-NO-SPLIT-NEXT:    str xzr, [x0, #8024]
; CHECK-NO-SPLIT-NEXT:    str xzr, [x0, #8032]
; CHECK-NO-SPLIT-NEXT:    str xzr, [x0, #8040]
; CHECK-NO-SPLIT-NEXT:    str xzr, [x0, #8048]
; CHECK-NO-SPLIT-NEXT:    str xzr, [x0, #8056]
; CHECK-NO-SPLIT-NEXT:    ret
;
; CHECK-SPLIT-LABEL: early_store_is_invalid_but_split_rest:
; CHECK-SPLIT:       ; %bb.0:
; CHECK-SPLIT-NEXT:    mov w8, #8016 ; =0x1f50
; CHECK-SPLIT-NEXT:    str xzr, [x0, #8000]
; CHECK-SPLIT-NEXT:    add x8, x0, x8
; CHECK-SPLIT-NEXT:    str xzr, [x0, #8080]
; CHECK-SPLIT-NEXT:    stp xzr, xzr, [x8]
; CHECK-SPLIT-NEXT:    stp xzr, xzr, [x8, #16]
; CHECK-SPLIT-NEXT:    stp xzr, xzr, [x8, #32]
; CHECK-SPLIT-NEXT:    ret
  %bigoffset = getelementptr i64, ptr %p, i64 1000
  store i64 0, ptr %bigoffset
  %addr2 = getelementptr i64, ptr %p, i64 1010
  store i64 0, ptr %addr2
  %addr3 = getelementptr i64, ptr %p, i64 1002
  store i64 0, ptr %addr3
  %addr4 = getelementptr i64, ptr %p, i64 1003
  store i64 0, ptr %addr4
  %addr5 = getelementptr i64, ptr %p, i64 1004
  store i64 0, ptr %addr5
  %addr6 = getelementptr i64, ptr %p, i64 1005
  store i64 0, ptr %addr6
  %addr7 = getelementptr i64, ptr %p, i64 1006
  store i64 0, ptr %addr7
  %addr8 = getelementptr i64, ptr %p, i64 1007
  store i64 0, ptr %addr8
  ret void
}

define void @vector(ptr %p) {
; CHECK-NO-SPLIT-LABEL: vector:
; CHECK-NO-SPLIT:       ; %bb.0:
; CHECK-NO-SPLIT-NEXT:    movi.2d v0, #0000000000000000
; CHECK-NO-SPLIT-NEXT:    str q0, [x0, #16000]
; CHECK-NO-SPLIT-NEXT:    str q0, [x0, #16016]
; CHECK-NO-SPLIT-NEXT:    str q0, [x0, #16032]
; CHECK-NO-SPLIT-NEXT:    str q0, [x0, #16048]
; CHECK-NO-SPLIT-NEXT:    str q0, [x0, #16064]
; CHECK-NO-SPLIT-NEXT:    str q0, [x0, #16080]
; CHECK-NO-SPLIT-NEXT:    str q0, [x0, #16096]
; CHECK-NO-SPLIT-NEXT:    str q0, [x0, #16112]
; CHECK-NO-SPLIT-NEXT:    ret
;
; CHECK-SPLIT-LABEL: vector:
; CHECK-SPLIT:       ; %bb.0:
; CHECK-SPLIT-NEXT:    movi.2d v0, #0000000000000000
; CHECK-SPLIT-NEXT:    mov w8, #16000 ; =0x3e80
; CHECK-SPLIT-NEXT:    add x8, x0, x8
; CHECK-SPLIT-NEXT:    stp q0, q0, [x8]
; CHECK-SPLIT-NEXT:    stp q0, q0, [x8, #32]
; CHECK-SPLIT-NEXT:    stp q0, q0, [x8, #64]
; CHECK-SPLIT-NEXT:    stp q0, q0, [x8, #96]
; CHECK-SPLIT-NEXT:    ret
  %bigoffset = getelementptr <2 x i64>, ptr %p, i64 1000
  store <2 x i64> <i64 0, i64 0>, ptr %bigoffset
  %addr2 = getelementptr <2 x i64>, ptr %p, i64 1001
  store <2 x i64> <i64 0, i64 0>, ptr %addr2
  %addr3 = getelementptr <2 x i64>, ptr %p, i64 1002
  store <2 x i64> <i64 0, i64 0>, ptr %addr3
  %addr4 = getelementptr <2 x i64>, ptr %p, i64 1003
  store <2 x i64> <i64 0, i64 0>, ptr %addr4
  %addr5 = getelementptr <2 x i64>, ptr %p, i64 1004
  store <2 x i64> <i64 0, i64 0>, ptr %addr5
  %addr6 = getelementptr <2 x i64>, ptr %p, i64 1005
  store <2 x i64> <i64 0, i64 0>, ptr %addr6
  %addr7 = getelementptr <2 x i64>, ptr %p, i64 1006
  store <2 x i64> <i64 0, i64 0>, ptr %addr7
  %addr8 = getelementptr <2 x i64>, ptr %p, i64 1007
  store <2 x i64> <i64 0, i64 0>, ptr %addr8
  ret void
}

define void @can_already_form_stp(ptr %p) {
; CHECK-NO-SPLIT-LABEL: can_already_form_stp:
; CHECK-NO-SPLIT:       ; %bb.0:
; CHECK-NO-SPLIT-NEXT:    stp xzr, xzr, [x0, #80]
; CHECK-NO-SPLIT-NEXT:    stp xzr, xzr, [x0, #96]
; CHECK-NO-SPLIT-NEXT:    stp xzr, xzr, [x0, #112]
; CHECK-NO-SPLIT-NEXT:    ret
;
; CHECK-SPLIT-LABEL: can_already_form_stp:
; CHECK-SPLIT:       ; %bb.0:
; CHECK-SPLIT-NEXT:    stp xzr, xzr, [x0, #80]
; CHECK-SPLIT-NEXT:    stp xzr, xzr, [x0, #96]
; CHECK-SPLIT-NEXT:    stp xzr, xzr, [x0, #112]
; CHECK-SPLIT-NEXT:    ret
  %bigoffset = getelementptr i64, ptr %p, i64 10
  store i64 0, ptr %bigoffset
  %addr2 = getelementptr i64, ptr %p, i64 11
  store i64 0, ptr %addr2
  %addr3 = getelementptr i64, ptr %p, i64 12
  store i64 0, ptr %addr3
  %addr4 = getelementptr i64, ptr %p, i64 13
  store i64 0, ptr %addr4
  %addr5 = getelementptr i64, ptr %p, i64 14
  store i64 0, ptr %addr5
  %addr6 = getelementptr i64, ptr %p, i64 15
  store i64 0, ptr %addr6
  ret void
}

define void @use_of_load_in_between(ptr %p, ptr %ldptr, ptr %ldptr2) {
; CHECK-NO-SPLIT-LABEL: use_of_load_in_between:
; CHECK-NO-SPLIT:       ; %bb.0:
; CHECK-NO-SPLIT-NEXT:    str xzr, [x0, #8000]
; CHECK-NO-SPLIT-NEXT:    ldr x8, [x1]
; CHECK-NO-SPLIT-NEXT:    str xzr, [x0, #8016]
; CHECK-NO-SPLIT-NEXT:    str x8, [x0, #8008]
; CHECK-NO-SPLIT-NEXT:    ldr x8, [x2]
; CHECK-NO-SPLIT-NEXT:    str xzr, [x0, #8032]
; CHECK-NO-SPLIT-NEXT:    str xzr, [x0, #8040]
; CHECK-NO-SPLIT-NEXT:    str x8, [x0, #8024]
; CHECK-NO-SPLIT-NEXT:    ret
;
; CHECK-SPLIT-LABEL: use_of_load_in_between:
; CHECK-SPLIT:       ; %bb.0:
; CHECK-SPLIT-NEXT:    str xzr, [x0, #8000]
; CHECK-SPLIT-NEXT:    ldr x8, [x1]
; CHECK-SPLIT-NEXT:    str xzr, [x0, #8016]
; CHECK-SPLIT-NEXT:    str x8, [x0, #8008]
; CHECK-SPLIT-NEXT:    ldr x8, [x2]
; CHECK-SPLIT-NEXT:    str xzr, [x0, #8032]
; CHECK-SPLIT-NEXT:    str xzr, [x0, #8040]
; CHECK-SPLIT-NEXT:    str x8, [x0, #8024]
; CHECK-SPLIT-NEXT:    ret
  %bigoffset = getelementptr i64, ptr %p, i64 1000
  store i64 0, ptr %bigoffset
  %addr2 = getelementptr i64, ptr %p, i64 1001
  %ld = load i64, ptr %ldptr
  store i64 %ld, ptr %addr2
  %addr3 = getelementptr i64, ptr %p, i64 1002
  store i64 0, ptr %addr3
  %addr4 = getelementptr i64, ptr %p, i64 1003
  %ld2 = load i64, ptr %ldptr2
  store i64 %ld2, ptr %addr4
  %addr5 = getelementptr i64, ptr %p, i64 1004
  store i64 0, ptr %addr5
  %addr6 = getelementptr i64, ptr %p, i64 1005
  store i64 0, ptr %addr6
  ret void
}

define void @offset_legal_for_add_imm(ptr %p) {
; CHECK-NO-SPLIT-LABEL: offset_legal_for_add_imm:
; CHECK-NO-SPLIT:       ; %bb.0:
; CHECK-NO-SPLIT-NEXT:    str xzr, [x0, #3200]
; CHECK-NO-SPLIT-NEXT:    str xzr, [x0, #3208]
; CHECK-NO-SPLIT-NEXT:    str xzr, [x0, #3216]
; CHECK-NO-SPLIT-NEXT:    ret
;
; CHECK-SPLIT-LABEL: offset_legal_for_add_imm:
; CHECK-SPLIT:       ; %bb.0:
; CHECK-SPLIT-NEXT:    add x8, x0, #3200
; CHECK-SPLIT-NEXT:    stp xzr, xzr, [x8]
; CHECK-SPLIT-NEXT:    str xzr, [x8, #16]
; CHECK-SPLIT-NEXT:    ret
  %bigoffset = getelementptr i64, ptr %p, i64 400
  store i64 0, ptr %bigoffset
  %addr2 = getelementptr i64, ptr %p, i64 401
  store i64 0, ptr %addr2
  %addr3 = getelementptr i64, ptr %p, i64 402
  store i64 0, ptr %addr3
  ret void
}

define void @offset_illegal_for_add_imm(ptr %p) {
; CHECK-NO-SPLIT-LABEL: offset_illegal_for_add_imm:
; CHECK-NO-SPLIT:       ; %bb.0:
; CHECK-NO-SPLIT-NEXT:    str xzr, [x0, #8000]
; CHECK-NO-SPLIT-NEXT:    str xzr, [x0, #8008]
; CHECK-NO-SPLIT-NEXT:    str xzr, [x0, #8016]
; CHECK-NO-SPLIT-NEXT:    ret
;
; CHECK-SPLIT-LABEL: offset_illegal_for_add_imm:
; CHECK-SPLIT:       ; %bb.0:
; CHECK-SPLIT-NEXT:    str xzr, [x0, #8000]
; CHECK-SPLIT-NEXT:    str xzr, [x0, #8008]
; CHECK-SPLIT-NEXT:    str xzr, [x0, #8016]
; CHECK-SPLIT-NEXT:    ret
  %bigoffset = getelementptr i64, ptr %p, i64 1000
  store i64 0, ptr %bigoffset
  %addr2 = getelementptr i64, ptr %p, i64 1001
  store i64 0, ptr %addr2
  %addr3 = getelementptr i64, ptr %p, i64 1002
  store i64 0, ptr %addr3
  ret void
}

define void @offset_legal_for_add_imm_4_stores(ptr %p) {
; CHECK-NO-SPLIT-LABEL: offset_legal_for_add_imm_4_stores:
; CHECK-NO-SPLIT:       ; %bb.0:
; CHECK-NO-SPLIT-NEXT:    str xzr, [x0, #3200]
; CHECK-NO-SPLIT-NEXT:    str xzr, [x0, #3208]
; CHECK-NO-SPLIT-NEXT:    str xzr, [x0, #3216]
; CHECK-NO-SPLIT-NEXT:    str xzr, [x0, #3224]
; CHECK-NO-SPLIT-NEXT:    ret
;
; CHECK-SPLIT-LABEL: offset_legal_for_add_imm_4_stores:
; CHECK-SPLIT:       ; %bb.0:
; CHECK-SPLIT-NEXT:    add x8, x0, #3200
; CHECK-SPLIT-NEXT:    stp xzr, xzr, [x8]
; CHECK-SPLIT-NEXT:    stp xzr, xzr, [x8, #16]
; CHECK-SPLIT-NEXT:    ret
  %bigoffset = getelementptr i64, ptr %p, i64 400
  store i64 0, ptr %bigoffset
  %addr2 = getelementptr i64, ptr %p, i64 401
  store i64 0, ptr %addr2
  %addr3 = getelementptr i64, ptr %p, i64 402
  store i64 0, ptr %addr3
  %addr4 = getelementptr i64, ptr %p, i64 403
  store i64 0, ptr %addr4
  ret void
}

define void @offset_illegal_for_add_imm_4_stores(ptr %p) {
; CHECK-NO-SPLIT-LABEL: offset_illegal_for_add_imm_4_stores:
; CHECK-NO-SPLIT:       ; %bb.0:
; CHECK-NO-SPLIT-NEXT:    str xzr, [x0, #8000]
; CHECK-NO-SPLIT-NEXT:    str xzr, [x0, #8008]
; CHECK-NO-SPLIT-NEXT:    str xzr, [x0, #8016]
; CHECK-NO-SPLIT-NEXT:    str xzr, [x0, #8024]
; CHECK-NO-SPLIT-NEXT:    ret
;
; CHECK-SPLIT-LABEL: offset_illegal_for_add_imm_4_stores:
; CHECK-SPLIT:       ; %bb.0:
; CHECK-SPLIT-NEXT:    mov w8, #8000 ; =0x1f40
; CHECK-SPLIT-NEXT:    add x8, x0, x8
; CHECK-SPLIT-NEXT:    stp xzr, xzr, [x8]
; CHECK-SPLIT-NEXT:    stp xzr, xzr, [x8, #16]
; CHECK-SPLIT-NEXT:    ret
  %bigoffset = getelementptr i64, ptr %p, i64 1000
  store i64 0, ptr %bigoffset
  %addr2 = getelementptr i64, ptr %p, i64 1001
  store i64 0, ptr %addr2
  %addr3 = getelementptr i64, ptr %p, i64 1002
  store i64 0, ptr %addr3
  %addr4 = getelementptr i64, ptr %p, i64 1003
  store i64 0, ptr %addr4
  ret void
}
