# 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, i32* @var1, align 4 %cmp = icmp eq i32 %0, 1 br i1 %cmp, label %if.then, label %if.end if.then: store i32 2, i32* @var2, align 4 store i32 3, i32* @var1, align 4 store i32 2, i32* @var3, align 4 store i32 3, i32* @var1, align 4 br label %if.end if.end: ret i32 0 } define i32 @adrp_add() { entry: %0 = load i32, i32* @var1, align 4 %cmp = icmp eq i32 %0, 1 br i1 %cmp, label %if.then, label %if.end if.then: store i32 2, i32* @var2, align 4 store i32 3, i32* @var1, align 4 store i32 2, i32* @var3, align 4 store i32 3, i32* @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_use_nonunique() { 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: [[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 ... --- 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_use_nonunique legalized: true regBankSelected: true tracksRegLiveness: true body: | ; CHECK-LABEL: name: non_local_phi_use_nonunique ; 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, because there are multiple edges ; using that register. 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 ...