The current algorithm just tries to localize defs as far as they can go, and in the case of G_PHI operands, it clones the def into the predecessor block for each incoming edge. When multiple edges have the same register value, this can cause unnecessary code bloat, and inhibit later optimizations. This change checks if a given phi operand is unique in the phi, if not the def of that register is not localized to the predecessor. Differential Revision: https://reviews.llvm.org/D95406
609 lines
20 KiB
YAML
609 lines
20 KiB
YAML
# 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 4 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 4 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 4 into @var1)
|
|
; CHECK: [[GV5:%[0-9]+]]:gpr(p0) = G_GLOBAL_VALUE @var3
|
|
; CHECK: G_STORE [[C4]](s32), [[GV5]](p0) :: (store 4 into @var3)
|
|
; CHECK: G_STORE [[C5]](s32), [[GV4]](p0) :: (store 4 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 4 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 4 into @var2)
|
|
G_STORE %6(s32), %1(p0) :: (store 4 into @var1)
|
|
G_STORE %4(s32), %7(p0) :: (store 4 into @var3)
|
|
G_STORE %6(s32), %1(p0) :: (store 4 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 4 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 4 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 4 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 4 into @var3)
|
|
; CHECK: G_STORE [[C5]](s32), [[ADD_LOW1]](p0) :: (store 4 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 4 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 4 into @var2)
|
|
G_STORE %6(s32), %addlow1(p0) :: (store 4 into @var1)
|
|
G_STORE %4(s32), %addlow3(p0) :: (store 4 into @var3)
|
|
G_STORE %6(s32), %addlow1(p0) :: (store 4 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 4)
|
|
; 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 4)
|
|
$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
|
|
...
|