# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
# RUN: llc -O0 -mtriple=aarch64-apple-ios -run-pass=localizer -verify-machineinstrs -global-isel %s -o - | FileCheck %s -check-prefix=CHECK

# Test the localizer.

--- |
  target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"

  define void @local_use() { ret void }
  define void @non_local_1use() { ret void }
  define void @non_local_2uses() { ret void }
  define void @non_local_phi_use() { ret void }
  define void @non_local_phi_use_followed_by_use() { ret void }
  define void @non_local_phi_use_followed_by_use_fi() { ret void }
  define void @float_non_local_phi_use_followed_by_use_fi() { ret void }
  define void @non_local_phi() { ret void }
  define void @non_local_label() { ret void }
...

---
name:            local_use
legalized:       true
regBankSelected: true
body:             |
  bb.0:
    ; CHECK-LABEL: name: local_use
    ; CHECK: [[C:%[0-9]+]]:gpr(s32) = G_CONSTANT 1
    ; CHECK: [[ADD:%[0-9]+]]:gpr(s32) = G_ADD [[C]], [[C]]
    %0:gpr(s32) = G_CONSTANT 1
    %1:gpr(s32) = G_ADD %0, %0
...

---
name:            non_local_1use
legalized:       true
regBankSelected: true
body:             |
  ; CHECK-LABEL: name: non_local_1use
  ; CHECK: bb.0:
  ; CHECK:   successors: %bb.1(0x80000000)
  ; CHECK:   [[C:%[0-9]+]]:gpr(s32) = G_CONSTANT 1
  ; CHECK:   [[ADD:%[0-9]+]]:gpr(s32) = G_ADD [[C]], [[C]]
  ; CHECK: bb.1:
  ; CHECK:   [[C1:%[0-9]+]]:gpr(s32) = G_CONSTANT 1
  ; CHECK:   [[ADD1:%[0-9]+]]:gpr(s32) = G_ADD [[C1]], [[ADD]]

  ; Existing registers should be left untouched
  ; The newly created reg should be on the same regbank/regclass as its origin.

  bb.0:
    successors: %bb.1

    %0:gpr(s32) = G_CONSTANT 1
    %1:gpr(s32) = G_ADD %0, %0

  bb.1:
    %2:gpr(s32) = G_ADD %0, %1
...

---
name:            non_local_2uses
legalized:       true
regBankSelected: true
body:             |
  ; CHECK-LABEL: name: non_local_2uses
  ; CHECK: bb.0:
  ; CHECK:   successors: %bb.1(0x80000000)
  ; CHECK:   [[C:%[0-9]+]]:gpr(s32) = G_CONSTANT 1
  ; CHECK:   [[ADD:%[0-9]+]]:gpr(s32) = G_ADD [[C]], [[C]]
  ; CHECK: bb.1:
  ; CHECK:   [[C1:%[0-9]+]]:gpr(s32) = G_CONSTANT 1
  ; CHECK:   [[ADD1:%[0-9]+]]:gpr(s32) = G_ADD [[C1]], [[C1]]

  ; Existing registers should be left untouched
  ; The newly created reg should be on the same regbank/regclass as its origin.

  bb.0:
    successors: %bb.1

    %0:gpr(s32) = G_CONSTANT 1
    %1:gpr(s32) = G_ADD %0, %0

  bb.1:
    %2:gpr(s32) = G_ADD %0, %0
...

---
name:            non_local_phi_use
legalized:       true
regBankSelected: true
tracksRegLiveness: true
body:             |
  ; CHECK-LABEL: name: non_local_phi_use
  ; CHECK: bb.0:
  ; CHECK:   successors: %bb.1(0x80000000)
  ; CHECK:   [[C:%[0-9]+]]:gpr(s32) = G_CONSTANT 1
  ; CHECK:   [[ADD:%[0-9]+]]:gpr(s32) = G_ADD [[C]], [[C]]
  ; CHECK: bb.1:
  ; CHECK:   successors: %bb.2(0x80000000)
  ; CHECK:   [[C1:%[0-9]+]]:gpr(s32) = G_CONSTANT 1
  ; CHECK: bb.2:
  ; CHECK:   [[PHI:%[0-9]+]]:gpr(s32) = PHI [[C1]](s32), %bb.1
  ; CHECK:   [[ADD1:%[0-9]+]]:gpr(s32) = G_ADD [[PHI]], [[PHI]]

  ; Existing registers should be left untouched
  ; The newly created reg should be on the same regbank/regclass as its origin.

  bb.0:
    successors: %bb.1

    %0:gpr(s32) = G_CONSTANT 1
    %1:gpr(s32) = G_ADD %0, %0

  bb.1:
    successors: %bb.2

  bb.2:
    %3:gpr(s32) = PHI %0(s32), %bb.1
    %2:gpr(s32) = G_ADD %3, %3
...

---
name:            non_local_phi_use_followed_by_use
legalized:       true
regBankSelected: true
tracksRegLiveness: true
body:             |
  ; CHECK-LABEL: name: non_local_phi_use_followed_by_use
  ; CHECK: bb.0:
  ; CHECK:   successors: %bb.1(0x80000000)
  ; CHECK:   [[C:%[0-9]+]]:gpr(s32) = G_CONSTANT 1
  ; CHECK:   [[ADD:%[0-9]+]]:gpr(s32) = G_ADD [[C]], [[C]]
  ; CHECK: bb.1:
  ; CHECK:   successors: %bb.2(0x80000000)
  ; CHECK:   [[C1:%[0-9]+]]:gpr(s32) = G_CONSTANT 1
  ; CHECK: bb.2:
  ; CHECK:   [[PHI:%[0-9]+]]:gpr(s32) = PHI [[C1]](s32), %bb.1
  ; CHECK:   [[C2:%[0-9]+]]:gpr(s32) = G_CONSTANT 1
  ; CHECK:   [[ADD1:%[0-9]+]]:gpr(s32) = G_ADD [[PHI]], [[C2]]

  ; Existing registers should be left untouched
  ; The newly created reg should be on the same regbank/regclass as its origin.

  bb.0:
    successors: %bb.1

    %0:gpr(s32) = G_CONSTANT 1
    %1:gpr(s32) = G_ADD %0, %0

  bb.1:
    successors: %bb.2

  bb.2:
    %3:gpr(s32) = PHI %0(s32), %bb.1
    %2:gpr(s32) = G_ADD %3, %0
...

---
name:            non_local_phi_use_followed_by_use_fi
legalized:       true
regBankSelected: true
tracksRegLiveness: true
body:             |
  ; CHECK-LABEL: name: non_local_phi_use_followed_by_use_fi
  ; CHECK: bb.0:
  ; CHECK:   successors: %bb.1(0x80000000)
  ; CHECK:   [[FRAME_INDEX:%[0-9]+]]:gpr(s32) = G_FRAME_INDEX 1
  ; CHECK:   [[ADD:%[0-9]+]]:gpr(s32) = G_ADD [[FRAME_INDEX]], [[FRAME_INDEX]]
  ; CHECK: bb.1:
  ; CHECK:   successors: %bb.2(0x80000000)
  ; CHECK:   [[FRAME_INDEX1:%[0-9]+]]:gpr(s32) = G_FRAME_INDEX 1
  ; CHECK: bb.2:
  ; CHECK:   [[PHI:%[0-9]+]]:gpr(s32) = PHI [[FRAME_INDEX1]](s32), %bb.1
  ; CHECK:   [[FRAME_INDEX2:%[0-9]+]]:gpr(s32) = G_FRAME_INDEX 1
  ; CHECK:   [[ADD1:%[0-9]+]]:gpr(s32) = G_ADD [[PHI]], [[FRAME_INDEX2]]

  ; Existing registers should be left untouched
  ; The newly created reg should be on the same regbank/regclass as its origin.

  bb.0:
    successors: %bb.1

    %0:gpr(s32) = G_FRAME_INDEX 1
    %1:gpr(s32) = G_ADD %0, %0

  bb.1:
    successors: %bb.2

  bb.2:
    %3:gpr(s32) = PHI %0(s32), %bb.1
    %2:gpr(s32) = G_ADD %3, %0
...

---
name:            float_non_local_phi_use_followed_by_use_fi
legalized:       true
regBankSelected: true
tracksRegLiveness: true
body:             |
  ; CHECK-LABEL: name: float_non_local_phi_use_followed_by_use_fi
  ; CHECK: bb.0:
  ; CHECK:   successors: %bb.1(0x80000000)
  ; CHECK:   [[C:%[0-9]+]]:fpr(s32) = G_FCONSTANT float 1.000000e+00
  ; CHECK:   [[FADD:%[0-9]+]]:fpr(s32) = G_FADD [[C]], [[C]]
  ; CHECK: bb.1:
  ; CHECK:   successors: %bb.2(0x80000000)
  ; CHECK:   [[C1:%[0-9]+]]:fpr(s32) = G_FCONSTANT float 1.000000e+00
  ; CHECK: bb.2:
  ; CHECK:   [[PHI:%[0-9]+]]:fpr(s32) = PHI [[C1]](s32), %bb.1
  ; CHECK:   [[C2:%[0-9]+]]:fpr(s32) = G_FCONSTANT float 1.000000e+00
  ; CHECK:   [[FADD1:%[0-9]+]]:fpr(s32) = G_FADD [[PHI]], [[C2]]

  ; Existing registers should be left untouched
  ; The newly created reg should be on the same regbank/regclass as its origin.

  bb.0:
    successors: %bb.1

    %0:fpr(s32) = G_FCONSTANT float 1.0
    %1:fpr(s32) = G_FADD %0, %0

  bb.1:
    successors: %bb.2

  bb.2:
    %3:fpr(s32) = PHI %0(s32), %bb.1
    %2:fpr(s32) = G_FADD %3, %0
...

---
# Make sure we don't insert a constant before PHIs.
# This used to happen for loops of one basic block.
name:            non_local_phi
legalized:       true
regBankSelected: true
tracksRegLiveness: true
body:             |
  ; CHECK-LABEL: name: non_local_phi
  ; CHECK: bb.0:
  ; CHECK:   successors: %bb.1(0x80000000)
  ; CHECK:   [[C:%[0-9]+]]:fpr(s32) = G_FCONSTANT float 1.000000e+00
  ; CHECK:   [[FADD:%[0-9]+]]:fpr(s32) = G_FADD [[C]], [[C]]
  ; CHECK: bb.1:
  ; CHECK:   successors: %bb.1(0x80000000)
  ; CHECK:   [[PHI:%[0-9]+]]:fpr(s32) = PHI [[FADD]](s32), %bb.0, %4(s32), %bb.1
  ; CHECK:   [[C1:%[0-9]+]]:fpr(s32) = G_FCONSTANT float 1.000000e+00
  ; CHECK:   [[FADD1:%[0-9]+]]:fpr(s32) = G_FADD [[PHI]], [[FADD]]
  ; CHECK:   G_BR %bb.1

  ; Existing registers should be left untouched
  ; The newly created reg should be on the same regbank/regclass as its origin.

  bb.0:
    successors: %bb.1

    %0:fpr(s32) = G_FCONSTANT float 1.0
    %1:fpr(s32) = G_FADD %0, %0

  bb.1:
    successors: %bb.1

    %3:fpr(s32) = PHI %1(s32), %bb.0, %0(s32), %bb.1
    %2:fpr(s32) = G_FADD %3, %1
    G_BR %bb.1
...

---
# Make sure we don't insert a constant before EH_LABELs.
name:            non_local_label
legalized:       true
regBankSelected: true
tracksRegLiveness: true
body:             |
  ; CHECK-LABEL: name: non_local_label
  ; CHECK: bb.0:
  ; CHECK:   successors: %bb.1(0x80000000)
  ; CHECK:   liveins: %s0
  ; CHECK:   [[COPY:%[0-9]+]]:fpr(s32) = COPY %s0
  ; CHECK:   [[C:%[0-9]+]]:fpr(s32) = G_FCONSTANT float 1.000000e+00
  ; CHECK: bb.1:
  ; CHECK:   successors: %bb.1(0x80000000)
  ; CHECK:   EH_LABEL 1
  ; CHECK:   [[C1:%[0-9]+]]:fpr(s32) = G_FCONSTANT float 1.000000e+00
  ; CHECK:   [[FADD:%[0-9]+]]:fpr(s32) = G_FADD [[COPY]], [[C1]]
  ; CHECK:   G_BR %bb.1

  ; Existing registers should be left untouched
  ; The newly created reg should be on the same regbank/regclass as its origin.

  bb.0:
    liveins: %s0
    successors: %bb.1

    %0:fpr(s32) = COPY %s0
    %1:fpr(s32) = G_FCONSTANT float 1.0

  bb.1:
    successors: %bb.1

    EH_LABEL 1
    %2:fpr(s32) = G_FADD %0, %1
    G_BR %bb.1
...