llvm/llvm/test/CodeGen/AArch64/GlobalISel/localizer.mir

# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
# RUN: llc -O0 -mtriple=aarch64-apple-ios -run-pass=localizer -verify-machineinstrs %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 }

  @var1 = common global i32 0, align 4
  @var2 = common global i32 0, align 4
  @var3 = common global i32 0, align 4
  @var4 = common global i32 0, align 4

  define i32 @intrablock_with_globalvalue() {
  entry:
    %0 = load i32, ptr @var1, align 4
    %cmp = icmp eq i32 %0, 1
    br i1 %cmp, label %if.then, label %if.end

  if.then:
    store i32 2, ptr @var2, align 4
    store i32 3, ptr @var1, align 4
    store i32 2, ptr @var3, align 4
    store i32 3, ptr @var1, align 4
    br label %if.end

  if.end:
    ret i32 0
  }
  define i32 @adrp_add() {
  entry:
    %0 = load i32, ptr @var1, align 4
    %cmp = icmp eq i32 %0, 1
    br i1 %cmp, label %if.then, label %if.end

  if.then:
    store i32 2, ptr @var2, align 4
    store i32 3, ptr @var1, align 4
    store i32 2, ptr @var3, align 4
    store i32 3, ptr @var1, align 4
    br label %if.end

  if.end:
    ret i32 0
  }

  define void @test_inttoptr() { ret void }
  define void @many_local_use_intra_block() { ret void }
  define void @non_local_phi_single_use() { ret void }
  define void @non_local_phi_three_uses() { 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 i32 1
    ; CHECK: [[ADD:%[0-9]+]]:gpr(s32) = G_ADD [[C]], [[C]]
    %0:gpr(s32) = G_CONSTANT i32 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 i32 1
  ; CHECK:   [[ADD:%[0-9]+]]:gpr(s32) = G_ADD [[C]], [[C]]
  ; CHECK: bb.1:
  ; CHECK:   [[C1:%[0-9]+]]:gpr(s32) = G_CONSTANT i32 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 i32 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 i32 1
  ; CHECK:   [[ADD:%[0-9]+]]:gpr(s32) = G_ADD [[C]], [[C]]
  ; CHECK: bb.1:
  ; CHECK:   [[C1:%[0-9]+]]:gpr(s32) = G_CONSTANT i32 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 i32 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 i32 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 i32 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 i32 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 i32 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 i32 1
  ; CHECK: bb.2:
  ; CHECK:   [[PHI:%[0-9]+]]:gpr(s32) = PHI [[C1]](s32), %bb.1
  ; CHECK:   [[C2:%[0-9]+]]:gpr(s32) = G_CONSTANT i32 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 i32 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:   [[FADD1:%[0-9]+]]:fpr(s32) = G_FADD [[PHI]], [[FADD]]
  ; CHECK:   [[C1:%[0-9]+]]:fpr(s32) = G_FCONSTANT float 1.000000e+00
  ; 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
...
---
name:            intrablock_with_globalvalue
legalized:       true
regBankSelected: true
tracksRegLiveness: true
body:             |
  ; CHECK-LABEL: name: intrablock_with_globalvalue
  ; CHECK: bb.0.entry:
  ; CHECK:   successors: %bb.1(0x40000000), %bb.2(0x40000000)
  ; CHECK:   [[C:%[0-9]+]]:gpr(s32) = G_CONSTANT i32 2
  ; CHECK:   [[GV:%[0-9]+]]:gpr(p0) = G_GLOBAL_VALUE @var2
  ; CHECK:   [[C1:%[0-9]+]]:gpr(s32) = G_CONSTANT i32 3
  ; CHECK:   [[GV1:%[0-9]+]]:gpr(p0) = G_GLOBAL_VALUE @var3
  ; CHECK:   [[C2:%[0-9]+]]:gpr(s32) = G_CONSTANT i32 0
  ; CHECK:   [[GV2:%[0-9]+]]:gpr(p0) = G_GLOBAL_VALUE @var1
  ; CHECK:   [[LOAD:%[0-9]+]]:gpr(s32) = G_LOAD [[GV2]](p0) :: (load (s32) from @var1)
  ; CHECK:   [[C3:%[0-9]+]]:gpr(s32) = G_CONSTANT i32 1
  ; CHECK:   [[ICMP:%[0-9]+]]:gpr(s32) = G_ICMP intpred(eq), [[LOAD]](s32), [[C3]]
  ; CHECK:   [[TRUNC:%[0-9]+]]:gpr(s1) = G_TRUNC [[ICMP]](s32)
  ; CHECK:   G_BRCOND [[TRUNC]](s1), %bb.1
  ; CHECK:   G_BR %bb.2
  ; CHECK: bb.1.if.then:
  ; CHECK:   successors: %bb.2(0x80000000)
  ; CHECK:   [[GV3:%[0-9]+]]:gpr(p0) = G_GLOBAL_VALUE @var2
  ; CHECK:   [[C4:%[0-9]+]]:gpr(s32) = G_CONSTANT i32 2
  ; CHECK:   G_STORE [[C4]](s32), [[GV3]](p0) :: (store (s32) into @var2)
  ; CHECK:   [[C5:%[0-9]+]]:gpr(s32) = G_CONSTANT i32 3
  ; CHECK:   [[GV4:%[0-9]+]]:gpr(p0) = G_GLOBAL_VALUE @var1
  ; CHECK:   G_STORE [[C5]](s32), [[GV4]](p0) :: (store (s32) into @var1)
  ; CHECK:   [[GV5:%[0-9]+]]:gpr(p0) = G_GLOBAL_VALUE @var3
  ; CHECK:   G_STORE [[C4]](s32), [[GV5]](p0) :: (store (s32) into @var3)
  ; CHECK:   G_STORE [[C5]](s32), [[GV4]](p0) :: (store (s32) into @var1)
  ; CHECK: bb.2.if.end:
  ; CHECK:   [[C6:%[0-9]+]]:gpr(s32) = G_CONSTANT i32 0
  ; CHECK:   $w0 = COPY [[C6]](s32)
  ; CHECK:   RET_ReallyLR implicit $w0

  ; Some of these instructions are dead. We're checking that the other instructions are
  ; sunk immediately before their first user in the if.then block or as close as possible.
  bb.1.entry:
    %1:gpr(p0) = G_GLOBAL_VALUE @var1
    %2:gpr(s32) = G_CONSTANT i32 1
    %4:gpr(s32) = G_CONSTANT i32 2
    %5:gpr(p0) = G_GLOBAL_VALUE @var2
    %6:gpr(s32) = G_CONSTANT i32 3
    %7:gpr(p0) = G_GLOBAL_VALUE @var3
    %8:gpr(s32) = G_CONSTANT i32 0
    %0:gpr(s32) = G_LOAD %1(p0) :: (load (s32) from @var1)
    %9:gpr(s32) = G_ICMP intpred(eq), %0(s32), %2
    %3:gpr(s1) = G_TRUNC %9(s32)
    G_BRCOND %3(s1), %bb.2
    G_BR %bb.3

  bb.2.if.then:
    G_STORE %4(s32), %5(p0) :: (store (s32) into @var2)
    G_STORE %6(s32), %1(p0) :: (store (s32) into @var1)
    G_STORE %4(s32), %7(p0) :: (store (s32) into @var3)
    G_STORE %6(s32), %1(p0) :: (store (s32) into @var1)

  bb.3.if.end:
    $w0 = COPY %8(s32)
    RET_ReallyLR implicit $w0

...
---
name:            adrp_add
legalized:       true
regBankSelected: true
tracksRegLiveness: true
body:             |
  ; CHECK-LABEL: name: adrp_add
  ; CHECK: bb.0.entry:
  ; CHECK:   successors: %bb.1(0x40000000), %bb.2(0x40000000)
  ; CHECK:   [[ADRP:%[0-9]+]]:gpr64(p0) = ADRP target-flags(aarch64-page) @var1
  ; CHECK:   %addlow1:gpr(p0) = G_ADD_LOW [[ADRP]](p0), target-flags(aarch64-pageoff, aarch64-nc) @var1
  ; CHECK:   [[C:%[0-9]+]]:gpr(s32) = G_CONSTANT i32 2
  ; CHECK:   [[ADRP1:%[0-9]+]]:gpr64(p0) = ADRP target-flags(aarch64-page) @var2
  ; CHECK:   %addlow2:gpr(p0) = G_ADD_LOW [[ADRP1]](p0), target-flags(aarch64-pageoff, aarch64-nc) @var2
  ; CHECK:   [[C1:%[0-9]+]]:gpr(s32) = G_CONSTANT i32 3
  ; CHECK:   [[ADRP2:%[0-9]+]]:gpr64(p0) = ADRP target-flags(aarch64-page) @var3
  ; CHECK:   %addlow3:gpr(p0) = G_ADD_LOW [[ADRP2]](p0), target-flags(aarch64-pageoff, aarch64-nc) @var3
  ; CHECK:   [[C2:%[0-9]+]]:gpr(s32) = G_CONSTANT i32 0
  ; CHECK:   [[LOAD:%[0-9]+]]:gpr(s32) = G_LOAD [[ADRP]](p0) :: (load (s32) from @var1)
  ; CHECK:   [[C3:%[0-9]+]]:gpr(s32) = G_CONSTANT i32 1
  ; CHECK:   [[ICMP:%[0-9]+]]:gpr(s32) = G_ICMP intpred(eq), [[LOAD]](s32), [[C3]]
  ; CHECK:   [[TRUNC:%[0-9]+]]:gpr(s1) = G_TRUNC [[ICMP]](s32)
  ; CHECK:   G_BRCOND [[TRUNC]](s1), %bb.1
  ; CHECK:   G_BR %bb.2
  ; CHECK: bb.1.if.then:
  ; CHECK:   successors: %bb.2(0x80000000)
  ; CHECK:   [[ADRP3:%[0-9]+]]:gpr64(p0) = ADRP target-flags(aarch64-page) @var2
  ; CHECK:   [[ADD_LOW:%[0-9]+]]:gpr(p0) = G_ADD_LOW [[ADRP3]](p0), target-flags(aarch64-pageoff, aarch64-nc) @var2
  ; CHECK:   [[C4:%[0-9]+]]:gpr(s32) = G_CONSTANT i32 2
  ; CHECK:   G_STORE [[C4]](s32), [[ADD_LOW]](p0) :: (store (s32) into @var2)
  ; CHECK:   [[C5:%[0-9]+]]:gpr(s32) = G_CONSTANT i32 3
  ; CHECK:   [[ADRP4:%[0-9]+]]:gpr64(p0) = ADRP target-flags(aarch64-page) @var1
  ; CHECK:   [[ADD_LOW1:%[0-9]+]]:gpr(p0) = G_ADD_LOW [[ADRP4]](p0), target-flags(aarch64-pageoff, aarch64-nc) @var1
  ; CHECK:   G_STORE [[C5]](s32), [[ADD_LOW1]](p0) :: (store (s32) into @var1)
  ; CHECK:   [[ADRP5:%[0-9]+]]:gpr64(p0) = ADRP target-flags(aarch64-page) @var3
  ; CHECK:   [[ADD_LOW2:%[0-9]+]]:gpr(p0) = G_ADD_LOW [[ADRP5]](p0), target-flags(aarch64-pageoff, aarch64-nc) @var3
  ; CHECK:   G_STORE [[C4]](s32), [[ADD_LOW2]](p0) :: (store (s32) into @var3)
  ; CHECK:   G_STORE [[C5]](s32), [[ADD_LOW1]](p0) :: (store (s32) into @var1)
  ; CHECK: bb.2.if.end:
  ; CHECK:   [[C6:%[0-9]+]]:gpr(s32) = G_CONSTANT i32 0
  ; CHECK:   $w0 = COPY [[C6]](s32)
  ; CHECK:   RET_ReallyLR implicit $w0

  ; Some of these instructions are dead.
  bb.1.entry:
    %1:gpr64(p0) = ADRP target-flags(aarch64-page) @var1
    %addlow1:gpr(p0) = G_ADD_LOW %1(p0), target-flags(aarch64-pageoff, aarch64-nc) @var1
    %2:gpr(s32) = G_CONSTANT i32 1
    %4:gpr(s32) = G_CONSTANT i32 2
    %5:gpr64(p0) = ADRP target-flags(aarch64-page) @var2
    %addlow2:gpr(p0) = G_ADD_LOW %5(p0), target-flags(aarch64-pageoff, aarch64-nc) @var2
    %6:gpr(s32) = G_CONSTANT i32 3
    %7:gpr64(p0) = ADRP target-flags(aarch64-page) @var3
    %addlow3:gpr(p0) = G_ADD_LOW %7(p0), target-flags(aarch64-pageoff, aarch64-nc) @var3
    %8:gpr(s32) = G_CONSTANT i32 0
    %0:gpr(s32) = G_LOAD %1(p0) :: (load (s32) from @var1)
    %9:gpr(s32) = G_ICMP intpred(eq), %0(s32), %2
    %3:gpr(s1) = G_TRUNC %9(s32)
    G_BRCOND %3(s1), %bb.2
    G_BR %bb.3

  bb.2.if.then:
    G_STORE %4(s32), %addlow2(p0) :: (store (s32) into @var2)
    G_STORE %6(s32), %addlow1(p0) :: (store (s32) into @var1)
    G_STORE %4(s32), %addlow3(p0) :: (store (s32) into @var3)
    G_STORE %6(s32), %addlow1(p0) :: (store (s32) into @var1)

  bb.3.if.end:
    $w0 = COPY %8(s32)
    RET_ReallyLR implicit $w0

...
---
name:            test_inttoptr
alignment:       4
legalized:       true
regBankSelected: true
tracksRegLiveness: true
body:             |
  ; CHECK-LABEL: name: test_inttoptr
  ; CHECK: bb.0:
  ; CHECK:   successors: %bb.1(0x40000000), %bb.2(0x40000000)
  ; CHECK:   liveins: $w0, $x1
  ; CHECK:   [[COPY:%[0-9]+]]:gpr(s32) = COPY $w0
  ; CHECK:   [[COPY1:%[0-9]+]]:gpr(p0) = COPY $x1
  ; CHECK:   [[C:%[0-9]+]]:gpr(s64) = G_CONSTANT i64 0
  ; CHECK:   [[INTTOPTR:%[0-9]+]]:gpr(p0) = G_INTTOPTR [[C]](s64)
  ; CHECK:   [[C1:%[0-9]+]]:gpr(s64) = G_CONSTANT i64 128
  ; CHECK:   [[INTTOPTR1:%[0-9]+]]:gpr(p0) = G_INTTOPTR [[C1]](s64)
  ; CHECK:   [[C2:%[0-9]+]]:gpr(s32) = G_CONSTANT i32 0
  ; CHECK:   [[ICMP:%[0-9]+]]:gpr(s32) = G_ICMP intpred(eq), [[COPY]](s32), [[C2]]
  ; CHECK:   [[TRUNC:%[0-9]+]]:gpr(s1) = G_TRUNC [[ICMP]](s32)
  ; CHECK:   G_BRCOND [[TRUNC]](s1), %bb.1
  ; CHECK:   G_BR %bb.2
  ; CHECK: bb.1:
  ; CHECK:   [[ADD:%[0-9]+]]:gpr(s32) = G_ADD [[COPY]], [[COPY]]
  ; CHECK:   G_STORE [[ADD]](s32), [[COPY1]](p0) :: (store (s32)
  ; CHECK:   [[C3:%[0-9]+]]:gpr(s64) = G_CONSTANT i64 128
  ; CHECK:   [[INTTOPTR2:%[0-9]+]]:gpr(p0) = G_INTTOPTR [[C3]](s64)
  ; CHECK:   $x0 = COPY [[INTTOPTR2]](p0)
  ; CHECK:   RET_ReallyLR implicit $x0
  ; CHECK: bb.2:
  ; CHECK:   [[C4:%[0-9]+]]:gpr(s64) = G_CONSTANT i64 0
  ; CHECK:   [[INTTOPTR3:%[0-9]+]]:gpr(p0) = G_INTTOPTR [[C4]](s64)
  ; CHECK:   $x0 = COPY [[INTTOPTR3]](p0)
  ; CHECK:   RET_ReallyLR implicit $x0
  bb.1:
    liveins: $w0, $x1

    %0:gpr(s32) = COPY $w0
    %1:gpr(p0) = COPY $x1
    %2:gpr(s64) = G_CONSTANT i64 128
    %4:gpr(s32) = G_CONSTANT i32 0
    %7:gpr(s64) = G_CONSTANT i64 0
    %6:gpr(p0) = G_INTTOPTR %7(s64)
    %3:gpr(p0) = G_INTTOPTR %2(s64)
    %9:gpr(s32) = G_ICMP intpred(eq), %0(s32), %4
    %5:gpr(s1) = G_TRUNC %9(s32)
    G_BRCOND %5(s1), %bb.2
    G_BR %bb.3

  bb.2:
    %8:gpr(s32) = G_ADD %0, %0
    G_STORE %8(s32), %1(p0) :: (store (s32))
    $x0 = COPY %3(p0)
    RET_ReallyLR implicit $x0

  bb.3:
    $x0 = COPY %6(p0)
    RET_ReallyLR implicit $x0

...

---
name:            many_local_use_intra_block
legalized:       true
regBankSelected: true
body:             |
  bb.0:
    ; CHECK-LABEL: name: many_local_use_intra_block
    ; CHECK: [[C:%[0-9]+]]:gpr(s32) = G_CONSTANT i32 1
    ; CHECK: [[ADD:%[0-9]+]]:gpr(s32) = G_ADD [[C]], [[C]]
    ; CHECK: [[ADD1:%[0-9]+]]:gpr(s32) = G_ADD [[C]], [[C]]
    ; CHECK: [[ADD2:%[0-9]+]]:gpr(s32) = G_ADD [[C]], [[C]]
    ; CHECK: [[ADD3:%[0-9]+]]:gpr(s32) = G_ADD [[C]], [[C]]
    ; CHECK: [[ADD4:%[0-9]+]]:gpr(s32) = G_ADD [[C]], [[C]]
    ; CHECK: [[C1:%[0-9]+]]:gpr(s32) = G_CONSTANT i32 2
    ; CHECK: [[ADD5:%[0-9]+]]:gpr(s32) = G_ADD [[C1]], [[C1]]
    %0:gpr(s32) = G_CONSTANT i32 1
    %1:gpr(s32) = G_CONSTANT i32 2
    %2:gpr(s32) = G_ADD %0, %0
    %3:gpr(s32) = G_ADD %0, %0
    %4:gpr(s32) = G_ADD %0, %0
    %5:gpr(s32) = G_ADD %0, %0
    %6:gpr(s32) = G_ADD %0, %0
    %7:gpr(s32) = G_ADD %1, %1
...

---
name:            non_local_phi_single_use
legalized:       true
regBankSelected: true
tracksRegLiveness: true
body:             |
  ; CHECK-LABEL: name: non_local_phi_single_use
  ; CHECK: bb.0:
  ; CHECK:   successors: %bb.1(0x40000000), %bb.2(0x40000000)
  ; CHECK:   [[C:%[0-9]+]]:gpr(s32) = G_CONSTANT i32 1
  ; CHECK:   [[ADD:%[0-9]+]]:gpr(s32) = G_ADD [[C]], [[C]]
  ; CHECK:   %cmp:gpr(s32) = G_ICMP intpred(eq), [[ADD]](s32), [[C]]
  ; CHECK:   %cond:gpr(s1) = G_TRUNC %cmp(s32)
  ; CHECK:   G_BRCOND %cond(s1), %bb.1
  ; CHECK:   G_BR %bb.2
  ; CHECK: bb.1:
  ; CHECK:   successors: %bb.2(0x80000000)
  ; CHECK:   [[C2:%[0-9]+]]:gpr(s32) = G_CONSTANT i32 1
  ; CHECK: bb.2:
  ; CHECK:   [[PHI:%[0-9]+]]:gpr(s32) = G_PHI [[C2]](s32), %bb.1
  ; CHECK:   [[ADD1:%[0-9]+]]:gpr(s32) = G_ADD [[PHI]], [[PHI]]

  ; Localize the 1 into bb.1, since the number of uses is under the threshold.

  bb.0:
    successors: %bb.1, %bb.2

    %0:gpr(s32) = G_CONSTANT i32 1
    %1:gpr(s32) = G_ADD %0, %0
    %cmp:gpr(s32) = G_ICMP intpred(eq), %1(s32), %0
    %cond:gpr(s1) = G_TRUNC %cmp(s32)
    G_BRCOND %cond(s1), %bb.1
    G_BR %bb.2

  bb.1:
    successors: %bb.2

  bb.2:
    %3:gpr(s32) = G_PHI %0(s32), %bb.1, %0(s32), %bb.0
    %2:gpr(s32) = G_ADD %3, %3
...
---
name:            non_local_phi_three_uses
legalized:       true
regBankSelected: true
tracksRegLiveness: true
body:             |
  ; CHECK-LABEL: name: non_local_phi_three_uses
  ; CHECK: bb.0:
  ; CHECK:   successors: %bb.1(0x40000000), %bb.2(0x40000000)
  ; CHECK:   [[C:%[0-9]+]]:gpr(s32) = G_CONSTANT i32 1
  ; CHECK:   [[ADD:%[0-9]+]]:gpr(s32) = G_ADD [[C]], [[C]]
  ; CHECK:   %cmp:gpr(s32) = G_ICMP intpred(eq), [[ADD]](s32), [[C]]
  ; CHECK:   %cond:gpr(s1) = G_TRUNC %cmp(s32)
  ; CHECK:   G_BRCOND %cond(s1), %bb.1
  ; CHECK:   G_BR %bb.2
  ; CHECK: bb.1:
  ; CHECK:   successors: %bb.2(0x80000000)
  ; CHECK: bb.2:
  ; CHECK:   [[PHI:%[0-9]+]]:gpr(s32) = G_PHI [[C]](s32), %bb.1
  ; CHECK:   [[ADD1:%[0-9]+]]:gpr(s32) = G_ADD [[PHI]], [[PHI]]

  ; Don't localize the 1 into bb.1, above the thresold of uses in the phi.

  bb.0:
    successors: %bb.1, %bb.2

    %0:gpr(s32) = G_CONSTANT i32 1
    %1:gpr(s32) = G_ADD %0, %0
    %cmp:gpr(s32) = G_ICMP intpred(eq), %1(s32), %0
    %cond:gpr(s1) = G_TRUNC %cmp(s32)
    G_BRCOND %cond(s1), %bb.1
    G_BR %bb.2

  bb.1:
    successors: %bb.2

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