# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5
# RUN: llc -mtriple aarch64-none-elf -mattr=+mte --run-pass=aarch64-ldst-opt %s -o - | FileCheck %s

## When generating code with sanitize_memtag, we make use of the fact that the
## sp+imm forms of many load and store instructions are not tag-checked, so we
## can use SP directly instead of needing a register holding the tagged
## pointer. However, this isn't true for the writeback versions of the
## instructions, so we can't fold ADDs and SUBs into them in
## AArch64LoadStoreOptimizer. This would be possible in cases where the
## loads/stores only access untagged stack slots, but that information isn't
## easily available after frame index elimination.

--- |
  define void @pre_index() {
  entry:
    ret void
  }
  define void @pre_index_memtag() sanitize_memtag {
  entry:
    ret void
  }
  define void @pre_index_memtag_not_sp() sanitize_memtag {
  entry:
    ret void
  }
  define void @post_index() {
  entry:
    ret void
  }
  define void @post_index_memtag() sanitize_memtag {
  entry:
    ret void
  }
  define void @post_index_memtag_not_sp() sanitize_memtag {
  entry:
    ret void
  }
...
---
name:            pre_index
body:             |
  bb.0.entry:
    liveins: $x0

    ; CHECK-LABEL: name: pre_index
    ; CHECK: liveins: $x0
    ; CHECK-NEXT: {{  $}}
    ; CHECK-NEXT: $sp = frame-setup SUBXri $sp, 16, 0
    ; CHECK-NEXT: early-clobber $sp = STRXpre killed renamable $x0, $sp, 16
    ; CHECK-NEXT: RET undef $lr
    $sp = frame-setup SUBXri $sp, 16, 0
    STRXui killed renamable $x0, $sp, 2
    $sp = ADDXri $sp, 16, 0
    RET undef $lr
...
---
name:            pre_index_memtag
body:             |
  bb.0.entry:
    liveins: $x0

    ; CHECK-LABEL: name: pre_index_memtag
    ; CHECK: liveins: $x0
    ; CHECK-NEXT: {{  $}}
    ; CHECK-NEXT: $sp = frame-setup SUBXri $sp, 16, 0
    ; CHECK-NEXT: STRXui killed renamable $x0, $sp, 2
    ; CHECK-NEXT: $sp = ADDXri $sp, 16, 0
    ; CHECK-NEXT: RET undef $lr
    $sp = frame-setup SUBXri $sp, 16, 0
    STRXui killed renamable $x0, $sp, 2
    $sp = ADDXri $sp, 16, 0
    RET undef $lr
...
---
name:            pre_index_memtag_not_sp
body:             |
  bb.0.entry:
    liveins: $x0, $x1

    ; CHECK-LABEL: name: pre_index_memtag_not_sp
    ; CHECK: liveins: $x0, $x1
    ; CHECK-NEXT: {{  $}}
    ; CHECK-NEXT: $x1 = frame-setup SUBXri $x1, 16, 0
    ; CHECK-NEXT: early-clobber $x1 = STRXpre killed renamable $x0, $x1, 16
    ; CHECK-NEXT: RET undef $lr, implicit $x1
    $x1 = frame-setup SUBXri $x1, 16, 0
    STRXui killed renamable $x0, $x1, 2
    $x1 = ADDXri $x1, 16, 0
    RET undef $lr, implicit $x1
...
---
name:            post_index
body:             |
  bb.0.entry:
    liveins: $x0

    ; CHECK-LABEL: name: post_index
    ; CHECK: liveins: $x0
    ; CHECK-NEXT: {{  $}}
    ; CHECK-NEXT: $sp = frame-setup SUBXri $sp, 16, 0
    ; CHECK-NEXT: early-clobber $sp = STRXpost killed renamable $x0, $sp, 16
    ; CHECK-NEXT: RET undef $lr
    $sp = frame-setup SUBXri $sp, 16, 0
    STRXui killed renamable $x0, $sp, 0
    $sp = ADDXri $sp, 16, 0
    RET undef $lr
...
---
name:            post_index_memtag
body:             |
  bb.0.entry:
    liveins: $x0

    ; CHECK-LABEL: name: post_index_memtag
    ; CHECK: liveins: $x0
    ; CHECK-NEXT: {{  $}}
    ; CHECK-NEXT: $sp = frame-setup SUBXri $sp, 16, 0
    ; CHECK-NEXT: STRXui killed renamable $x0, $sp, 0
    ; CHECK-NEXT: $sp = ADDXri $sp, 16, 0
    ; CHECK-NEXT: RET undef $lr
    $sp = frame-setup SUBXri $sp, 16, 0
    STRXui killed renamable $x0, $sp, 0
    $sp = ADDXri $sp, 16, 0
    RET undef $lr
...
---
name:            post_index_memtag_not_sp
body:             |
  bb.0.entry:
    liveins: $x0, $x1

    ; CHECK-LABEL: name: post_index_memtag_not_sp
    ; CHECK: liveins: $x0, $x1
    ; CHECK-NEXT: {{  $}}
    ; CHECK-NEXT: $x1 = frame-setup SUBXri $x1, 16, 0
    ; CHECK-NEXT: early-clobber $x1 = STRXpost killed renamable $x0, $x1, 16
    ; CHECK-NEXT: RET undef $lr, implicit $x1
    $x1 = frame-setup SUBXri $x1, 16, 0
    STRXui killed renamable $x0, $x1, 0
    $x1 = ADDXri $x1, 16, 0
    RET undef $lr, implicit $x1
...
