diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2016-07-23 20:41:05 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2016-07-23 20:41:05 +0000 |
commit | 01095a5d43bbfde13731688ddcf6048ebb8b7721 (patch) | |
tree | 4def12e759965de927d963ac65840d663ef9d1ea /test/CodeGen/AArch64/GlobalISel | |
parent | f0f4822ed4b66e3579e92a89f368f8fb860e218e (diff) | |
download | src-01095a5d43bbfde13731688ddcf6048ebb8b7721.tar.gz src-01095a5d43bbfde13731688ddcf6048ebb8b7721.zip |
Vendor import of llvm release_39 branch r276489:vendor/llvm/llvm-release_39-r276489
Notes
Notes:
svn path=/vendor/llvm/dist/; revision=303231
svn path=/vendor/llvm/llvm-release_39-r276489/; revision=303232; tag=vendor/llvm/llvm-release_39-r276489
Diffstat (limited to 'test/CodeGen/AArch64/GlobalISel')
-rw-r--r-- | test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll | 63 | ||||
-rw-r--r-- | test/CodeGen/AArch64/GlobalISel/arm64-regbankselect.mir | 329 |
2 files changed, 392 insertions, 0 deletions
diff --git a/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll b/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll new file mode 100644 index 000000000000..7d416d9b0add --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll @@ -0,0 +1,63 @@ +; RUN: llc -O0 -stop-after=irtranslator -global-isel -verify-machineinstrs %s -o - 2>&1 | FileCheck %s +; REQUIRES: global-isel +; This file checks that the translation from llvm IR to generic MachineInstr +; is correct. +target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" +target triple = "aarch64-apple-ios" + +; Tests for add. +; CHECK: name: addi64 +; CHECK: [[ARG1:%[0-9]+]](64) = COPY %x0 +; CHECK-NEXT: [[ARG2:%[0-9]+]](64) = COPY %x1 +; CHECK-NEXT: [[RES:%[0-9]+]](64) = G_ADD i64 [[ARG1]], [[ARG2]] +; CHECK-NEXT: %x0 = COPY [[RES]] +; CHECK-NEXT: RET_ReallyLR implicit %x0 +define i64 @addi64(i64 %arg1, i64 %arg2) { + %res = add i64 %arg1, %arg2 + ret i64 %res +} + +; Tests for br. +; CHECK: name: uncondbr +; CHECK: body: +; +; Entry basic block. +; CHECK: {{[0-9a-zA-Z._-]+}}: +; +; Make sure we have one successor and only one. +; CHECK-NEXT: successors: %[[END:[0-9a-zA-Z._-]+]]({{0x[a-f0-9]+ / 0x[a-f0-9]+}} = 100.00%) +; +; Check that we emit the correct branch. +; CHECK: G_BR label %[[END]] +; +; Check that end contains the return instruction. +; CHECK: [[END]]: +; CHECK-NEXT: RET_ReallyLR +define void @uncondbr() { + br label %end +end: + ret void +} + +; Tests for or. +; CHECK: name: ori64 +; CHECK: [[ARG1:%[0-9]+]](64) = COPY %x0 +; CHECK-NEXT: [[ARG2:%[0-9]+]](64) = COPY %x1 +; CHECK-NEXT: [[RES:%[0-9]+]](64) = G_OR i64 [[ARG1]], [[ARG2]] +; CHECK-NEXT: %x0 = COPY [[RES]] +; CHECK-NEXT: RET_ReallyLR implicit %x0 +define i64 @ori64(i64 %arg1, i64 %arg2) { + %res = or i64 %arg1, %arg2 + ret i64 %res +} + +; CHECK: name: ori32 +; CHECK: [[ARG1:%[0-9]+]](32) = COPY %w0 +; CHECK-NEXT: [[ARG2:%[0-9]+]](32) = COPY %w1 +; CHECK-NEXT: [[RES:%[0-9]+]](32) = G_OR i32 [[ARG1]], [[ARG2]] +; CHECK-NEXT: %w0 = COPY [[RES]] +; CHECK-NEXT: RET_ReallyLR implicit %w0 +define i32 @ori32(i32 %arg1, i32 %arg2) { + %res = or i32 %arg1, %arg2 + ret i32 %res +} diff --git a/test/CodeGen/AArch64/GlobalISel/arm64-regbankselect.mir b/test/CodeGen/AArch64/GlobalISel/arm64-regbankselect.mir new file mode 100644 index 000000000000..f5d85e189d75 --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/arm64-regbankselect.mir @@ -0,0 +1,329 @@ +# RUN: llc -O0 -run-pass=regbankselect -global-isel %s -o - 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=FAST +# RUN: llc -O0 -run-pass=regbankselect -global-isel %s -regbankselect-greedy -o - 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=GREEDY +# REQUIRES: global-isel + +--- | + ; ModuleID = 'generic-virtual-registers-type-error.mir' + target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + target triple = "aarch64-apple-ios" + define void @defaultMapping() { + entry: + ret void + } + define void @defaultMappingVector() { + entry: + ret void + } + define void @defaultMapping1Repair() { + entry: + ret void + } + define void @defaultMapping2Repairs() { + entry: + ret void + } + define void @defaultMappingDefRepair() { + entry: + ret void + } + define void @phiPropagation(i32* %src, i32* %dst, i1 %cond) { + entry: + %srcVal = load i32, i32* %src + br i1 %cond, label %end, label %then + then: + %res = add i32 %srcVal, 36 + br label %end + end: + %toStore = phi i32 [ %srcVal, %entry ], [ %res, %then ] + store i32 %toStore, i32* %dst + ret void + } + define void @defaultMappingUseRepairPhysReg() { + entry: + ret void + } + define void @defaultMappingDefRepairPhysReg() { + entry: + ret void + } + define void @greedyMappingOr() { + entry: + ret void + } + define void @greedyMappingOrWithConstraints() { + entry: + ret void + } +... + +--- +# Check that we assign a relevant register bank for %0. +# Based on the type i32, this should be gpr. +name: defaultMapping +isSSA: true +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr } +registers: + - { id: 0, class: _ } +body: | + bb.0.entry: + liveins: %x0 + ; CHECK: %0(32) = G_ADD i32 %x0 + %0(32) = G_ADD i32 %x0, %x0 +... + +--- +# Check that we assign a relevant register bank for %0. +# Based on the type <2 x i32>, this should be fpr. +# FPR is used for both floating point and vector registers. +name: defaultMappingVector +isSSA: true +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: fpr } +registers: + - { id: 0, class: _ } +body: | + bb.0.entry: + liveins: %d0 + ; CHECK: %0(32) = G_ADD <2 x i32> %d0 + %0(32) = G_ADD <2 x i32> %d0, %d0 +... + +--- +# Check that we repair the assignment for %0. +# Indeed based on the source of the copy it should live +# in FPR, but at the use, it should be GPR. +name: defaultMapping1Repair +isSSA: true +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: fpr } +# CHECK-NEXT: - { id: 1, class: gpr } +# CHECK-NEXT: - { id: 2, class: gpr } +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } +body: | + bb.0.entry: + liveins: %s0, %x0 + ; CHECK: %0(32) = COPY %s0 + ; CHECK-NEXT: %2(32) = COPY %0 + ; CHECK-NEXT: %1(32) = G_ADD i32 %2, %x0 + %0(32) = COPY %s0 + %1(32) = G_ADD i32 %0, %x0 +... + +# Check that we repair the assignment for %0 differently for both uses. +name: defaultMapping2Repairs +isSSA: true +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: fpr } +# CHECK-NEXT: - { id: 1, class: gpr } +# CHECK-NEXT: - { id: 2, class: gpr } +# CHECK-NEXT: - { id: 3, class: gpr } +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } +body: | + bb.0.entry: + liveins: %s0, %x0 + ; CHECK: %0(32) = COPY %s0 + ; CHECK-NEXT: %2(32) = COPY %0 + ; CHECK-NEXT: %3(32) = COPY %0 + ; CHECK-NEXT: %1(32) = G_ADD i32 %2, %3 + %0(32) = COPY %s0 + %1(32) = G_ADD i32 %0, %0 +... + +--- +# Check that we repair the definition of %1. +# %1 is forced to be into FPR, but its definition actually +# requires that it lives in GPR. Make sure regbankselect +# fixes that. +name: defaultMappingDefRepair +isSSA: true +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr } +# CHECK-NEXT: - { id: 1, class: fpr } +# CHECK-NEXT: - { id: 2, class: gpr } +registers: + - { id: 0, class: _ } + - { id: 1, class: fpr } +body: | + bb.0.entry: + liveins: %w0 + ; CHECK: %0(32) = COPY %w0 + ; CHECK-NEXT: %2(32) = G_ADD i32 %0, %w0 + ; CHECK-NEXT: %1(32) = COPY %2 + %0(32) = COPY %w0 + %1(32) = G_ADD i32 %0, %w0 +... + +--- +# Check that we are able to propagate register banks from phis. +name: phiPropagation +isSSA: true +tracksRegLiveness: true +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr32 } +# CHECK-NEXT: - { id: 1, class: gpr64sp } +# CHECK-NEXT: - { id: 2, class: gpr32 } +# CHECK-NEXT: - { id: 3, class: gpr } +# CHECK-NEXT: - { id: 4, class: gpr } +registers: + - { id: 0, class: gpr32 } + - { id: 1, class: gpr64sp } + - { id: 2, class: gpr32 } + - { id: 3, class: _ } + - { id: 4, class: _ } +body: | + bb.0.entry: + successors: %bb.2.end, %bb.1.then + liveins: %x0, %x1, %w2 + + %0 = LDRWui killed %x0, 0 :: (load 4 from %ir.src) + %1 = COPY %x1 + %2 = COPY %w2 + TBNZW killed %2, 0, %bb.2.end + + bb.1.then: + successors: %bb.2.end + %3(32) = G_ADD i32 %0, %0 + + bb.2.end: + %4(32) = PHI %0, %bb.0.entry, %3, %bb.1.then + STRWui killed %4, killed %1, 0 :: (store 4 into %ir.dst) + RET_ReallyLR +... + +--- +# Make sure we can repair physical register uses as well. +name: defaultMappingUseRepairPhysReg +isSSA: true +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr } +# CHECK-NEXT: - { id: 1, class: gpr } +# CHECK-NEXT: - { id: 2, class: gpr } +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } +body: | + bb.0.entry: + liveins: %w0, %s0 + ; CHECK: %0(32) = COPY %w0 + ; CHECK-NEXT: %2(32) = COPY %s0 + ; CHECK-NEXT: %1(32) = G_ADD i32 %0, %2 + %0(32) = COPY %w0 + %1(32) = G_ADD i32 %0, %s0 +... + +--- +# Make sure we can repair physical register defs. +name: defaultMappingDefRepairPhysReg +isSSA: true +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr } +# CHECK-NEXT: - { id: 1, class: gpr } +registers: + - { id: 0, class: _ } +body: | + bb.0.entry: + liveins: %w0 + ; CHECK: %0(32) = COPY %w0 + ; CHECK-NEXT: %1(32) = G_ADD i32 %0, %0 + ; CHECK-NEXT: %s0 = COPY %1 + %0(32) = COPY %w0 + %s0 = G_ADD i32 %0, %0 +... + +--- +# Check that the greedy mode is able to switch the +# G_OR instruction from fpr to gpr. +name: greedyMappingOr +isSSA: true +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr } +# CHECK-NEXT: - { id: 1, class: gpr } + +# Fast mode maps vector instruction on FPR. +# FAST-NEXT: - { id: 2, class: fpr } +# Fast mode needs two extra copies. +# FAST-NEXT: - { id: 3, class: fpr } +# FAST-NEXT: - { id: 4, class: fpr } + +# Greedy mode coalesce the computation on the GPR register +# because it is the cheapest. +# GREEDY-NEXT: - { id: 2, class: gpr } + +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } + - { id: 2, class: _ } +body: | + bb.0.entry: + liveins: %x0, %x1 + ; CHECK: %0(64) = COPY %x0 + ; CHECK-NEXT: %1(64) = COPY %x1 + + + ; Fast mode tries to reuse the source of the copy for the destination. + ; Now, the default mapping says that %0 and %1 need to be in FPR. + ; The repairing code insert two copies to materialize that. + ; FAST-NEXT: %3(64) = COPY %0 + ; FAST-NEXT: %4(64) = COPY %1 + ; The mapping of G_OR is on FPR. + ; FAST-NEXT: %2(64) = G_OR <2 x i32> %3, %4 + + ; Greedy mode remapped the instruction on the GPR bank. + ; GREEDY-NEXT: %2(64) = G_OR <2 x i32> %0, %1 + %0(64) = COPY %x0 + %1(64) = COPY %x1 + %2(64) = G_OR <2 x i32> %0, %1 +... + +--- +# Check that the greedy mode is able to switch the +# G_OR instruction from fpr to gpr, while still honoring +# %2 constraint. +name: greedyMappingOrWithConstraints +isSSA: true +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr } +# CHECK-NEXT: - { id: 1, class: gpr } +# CHECK-NEXT: - { id: 2, class: fpr } + +# Fast mode maps vector instruction on FPR. +# Fast mode needs two extra copies. +# FAST-NEXT: - { id: 3, class: fpr } +# FAST-NEXT: - { id: 4, class: fpr } + +# Greedy mode coalesce the computation on the GPR register because it +# is the cheapest, but will need one extra copy to materialize %2 into a FPR. +# GREEDY-NEXT: - { id: 3, class: gpr } + +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } + - { id: 2, class: fpr } +body: | + bb.0.entry: + liveins: %x0, %x1 + ; CHECK: %0(64) = COPY %x0 + ; CHECK-NEXT: %1(64) = COPY %x1 + + + ; Fast mode tries to reuse the source of the copy for the destination. + ; Now, the default mapping says that %0 and %1 need to be in FPR. + ; The repairing code insert two copies to materialize that. + ; FAST-NEXT: %3(64) = COPY %0 + ; FAST-NEXT: %4(64) = COPY %1 + ; The mapping of G_OR is on FPR. + ; FAST-NEXT: %2(64) = G_OR <2 x i32> %3, %4 + + ; Greedy mode remapped the instruction on the GPR bank. + ; GREEDY-NEXT: %3(64) = G_OR <2 x i32> %0, %1 + ; We need to keep %2 into FPR because we do not know anything about it. + ; GREEDY-NEXT: %2(64) = COPY %3 + %0(64) = COPY %x0 + %1(64) = COPY %x1 + %2(64) = G_OR <2 x i32> %0, %1 +... |