blob: 1eee40dd64867e6d351672c33ced7ba5bad8f964 [file] [log] [blame]
# 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 void @test_inttoptr() { 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: [[GV:%[0-9]+]]:gpr(p0) = G_GLOBAL_VALUE @var1
; CHECK: [[C:%[0-9]+]]:gpr(s32) = G_CONSTANT i32 1
; CHECK: [[C1:%[0-9]+]]:gpr(s32) = G_CONSTANT i32 2
; CHECK: [[GV1:%[0-9]+]]:gpr(p0) = G_GLOBAL_VALUE @var2
; CHECK: [[C2:%[0-9]+]]:gpr(s32) = G_CONSTANT i32 3
; CHECK: [[GV2:%[0-9]+]]:gpr(p0) = G_GLOBAL_VALUE @var3
; CHECK: [[C3:%[0-9]+]]:gpr(s32) = G_CONSTANT i32 0
; CHECK: [[LOAD:%[0-9]+]]:gpr(s32) = G_LOAD [[GV]](p0) :: (load 4 from @var1)
; CHECK: [[ICMP:%[0-9]+]]:gpr(s32) = G_ICMP intpred(eq), [[LOAD]](s32), [[C]]
; 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: 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 128
; CHECK: [[C1:%[0-9]+]]:gpr(s32) = G_CONSTANT i32 0
; CHECK: [[C2:%[0-9]+]]:gpr(s64) = G_CONSTANT i64 0
; CHECK: [[INTTOPTR:%[0-9]+]]:gpr(p0) = G_INTTOPTR [[C2]](s64)
; CHECK: [[INTTOPTR1:%[0-9]+]]:gpr(p0) = G_INTTOPTR [[C]](s64)
; CHECK: [[ICMP:%[0-9]+]]:gpr(s32) = G_ICMP intpred(eq), [[COPY]](s32), [[C1]]
; 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
...