diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2014-11-24 09:08:18 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2014-11-24 09:08:18 +0000 |
| commit | 5ca98fd98791947eba83a1ed3f2c8191ef7afa6c (patch) | |
| tree | f5944309621cee4fe0976be6f9ac619b7ebfc4c2 /test/CodeGen/XCore | |
| parent | 68bcb7db193e4bc81430063148253d30a791023e (diff) | |
Notes
Diffstat (limited to 'test/CodeGen/XCore')
| -rw-r--r-- | test/CodeGen/XCore/align.ll | 15 | ||||
| -rw-r--r-- | test/CodeGen/XCore/atomic.ll | 76 | ||||
| -rw-r--r-- | test/CodeGen/XCore/bigstructret.ll | 39 | ||||
| -rw-r--r-- | test/CodeGen/XCore/byVal.ll | 2 | ||||
| -rw-r--r-- | test/CodeGen/XCore/call.ll | 10 | ||||
| -rw-r--r-- | test/CodeGen/XCore/codemodel.ll | 213 | ||||
| -rw-r--r-- | test/CodeGen/XCore/dwarf_debug.ll | 39 | ||||
| -rw-r--r-- | test/CodeGen/XCore/epilogue_prologue.ll | 249 | ||||
| -rw-r--r-- | test/CodeGen/XCore/exception.ll | 3 | ||||
| -rw-r--r-- | test/CodeGen/XCore/globals.ll | 53 | ||||
| -rw-r--r-- | test/CodeGen/XCore/inline-asm.ll | 21 | ||||
| -rw-r--r-- | test/CodeGen/XCore/linkage.ll | 12 | ||||
| -rw-r--r-- | test/CodeGen/XCore/lit.local.cfg | 3 | ||||
| -rw-r--r-- | test/CodeGen/XCore/llvm-intrinsics.ll | 361 | ||||
| -rw-r--r-- | test/CodeGen/XCore/load.ll | 2 | ||||
| -rw-r--r-- | test/CodeGen/XCore/memcpy.ll | 32 | ||||
| -rw-r--r-- | test/CodeGen/XCore/resources.ll | 16 | ||||
| -rw-r--r-- | test/CodeGen/XCore/resources_combine.ll | 93 | ||||
| -rw-r--r-- | test/CodeGen/XCore/scavenging.ll | 69 |
19 files changed, 1280 insertions, 28 deletions
diff --git a/test/CodeGen/XCore/align.ll b/test/CodeGen/XCore/align.ll new file mode 100644 index 000000000000..2878a648e09b --- /dev/null +++ b/test/CodeGen/XCore/align.ll @@ -0,0 +1,15 @@ +; RUN: llc < %s -march=xcore | FileCheck %s + +; CHECK: .align 4 +; CHECK-LABEL: f: +define void @f() nounwind { +entry: + ret void +} + +; CHECK: .align 2 +; CHECK-LABEL: g: +define void @g() nounwind optsize { +entry: + ret void +} diff --git a/test/CodeGen/XCore/atomic.ll b/test/CodeGen/XCore/atomic.ll index 95fca9ac5b21..58ef38bd3f60 100644 --- a/test/CodeGen/XCore/atomic.ll +++ b/test/CodeGen/XCore/atomic.ll @@ -14,3 +14,79 @@ entry: fence seq_cst ret void } + +@pool = external global i64 + +define void @atomicloadstore() nounwind { +entry: +; CHECK-LABEL: atomicloadstore + +; CHECK: ldw r[[R0:[0-9]+]], dp[pool] +; CHECK-NEXT: #MEMBARRIER + %0 = load atomic i32* bitcast (i64* @pool to i32*) acquire, align 4 + +; CHECK-NEXT: ldaw r[[R1:[0-9]+]], dp[pool] +; CHECK-NEXT: ldc r[[R2:[0-9]+]], 0 + +; CHECK-NEXT: ld16s r3, r[[R1]][r[[R2]]] +; CHECK-NEXT: #MEMBARRIER + %1 = load atomic i16* bitcast (i64* @pool to i16*) acquire, align 2 + +; CHECK-NEXT: ld8u r11, r[[R1]][r[[R2]]] +; CHECK-NEXT: #MEMBARRIER + %2 = load atomic i8* bitcast (i64* @pool to i8*) acquire, align 1 + +; CHECK-NEXT: ldw r4, dp[pool] +; CHECK-NEXT: #MEMBARRIER + %3 = load atomic i32* bitcast (i64* @pool to i32*) seq_cst, align 4 + +; CHECK-NEXT: ld16s r5, r[[R1]][r[[R2]]] +; CHECK-NEXT: #MEMBARRIER + %4 = load atomic i16* bitcast (i64* @pool to i16*) seq_cst, align 2 + +; CHECK-NEXT: ld8u r6, r[[R1]][r[[R2]]] +; CHECK-NEXT: #MEMBARRIER + %5 = load atomic i8* bitcast (i64* @pool to i8*) seq_cst, align 1 + +; CHECK-NEXT: #MEMBARRIER +; CHECK-NEXT: stw r[[R0]], dp[pool] + store atomic i32 %0, i32* bitcast (i64* @pool to i32*) release, align 4 + +; CHECK-NEXT: #MEMBARRIER +; CHECK-NEXT: st16 r3, r[[R1]][r[[R2]]] + store atomic i16 %1, i16* bitcast (i64* @pool to i16*) release, align 2 + +; CHECK-NEXT: #MEMBARRIER +; CHECK-NEXT: st8 r11, r[[R1]][r[[R2]]] + store atomic i8 %2, i8* bitcast (i64* @pool to i8*) release, align 1 + +; CHECK-NEXT: #MEMBARRIER +; CHECK-NEXT: stw r4, dp[pool] +; CHECK-NEXT: #MEMBARRIER + store atomic i32 %3, i32* bitcast (i64* @pool to i32*) seq_cst, align 4 + +; CHECK-NEXT: #MEMBARRIER +; CHECK-NEXT: st16 r5, r[[R1]][r[[R2]]] +; CHECK-NEXT: #MEMBARRIER + store atomic i16 %4, i16* bitcast (i64* @pool to i16*) seq_cst, align 2 + +; CHECK-NEXT: #MEMBARRIER +; CHECK-NEXT: st8 r6, r[[R1]][r[[R2]]] +; CHECK-NEXT: #MEMBARRIER + store atomic i8 %5, i8* bitcast (i64* @pool to i8*) seq_cst, align 1 + +; CHECK-NEXT: ldw r[[R0]], dp[pool] +; CHECK-NEXT: stw r[[R0]], dp[pool] +; CHECK-NEXT: ld16s r[[R0]], r[[R1]][r[[R2]]] +; CHECK-NEXT: st16 r[[R0]], r[[R1]][r[[R2]]] +; CHECK-NEXT: ld8u r[[R0]], r[[R1]][r[[R2]]] +; CHECK-NEXT: st8 r[[R0]], r[[R1]][r[[R2]]] + %6 = load atomic i32* bitcast (i64* @pool to i32*) monotonic, align 4 + store atomic i32 %6, i32* bitcast (i64* @pool to i32*) monotonic, align 4 + %7 = load atomic i16* bitcast (i64* @pool to i16*) monotonic, align 2 + store atomic i16 %7, i16* bitcast (i64* @pool to i16*) monotonic, align 2 + %8 = load atomic i8* bitcast (i64* @pool to i8*) monotonic, align 1 + store atomic i8 %8, i8* bitcast (i64* @pool to i8*) monotonic, align 1 + + ret void +} diff --git a/test/CodeGen/XCore/bigstructret.ll b/test/CodeGen/XCore/bigstructret.ll index 877c57140a1d..567b37209195 100644 --- a/test/CodeGen/XCore/bigstructret.ll +++ b/test/CodeGen/XCore/bigstructret.ll @@ -3,8 +3,8 @@ %0 = type { i32, i32, i32, i32 } %1 = type { i32, i32, i32, i32, i32 } -; Structs of 4 words can be returned in registers -define internal fastcc %0 @ReturnBigStruct() nounwind readnone { +; Structs of 4 words are returned in registers +define internal %0 @ReturnBigStruct() nounwind readnone { entry: %0 = insertvalue %0 zeroinitializer, i32 12, 0 %1 = insertvalue %0 %0, i32 24, 1 @@ -19,8 +19,39 @@ entry: ; CHECK: ldc r3, 24601 ; CHECK: retsp 0 -; Structs bigger than 4 words are returned via a hidden hidden sret-parameter -define internal fastcc %1 @ReturnBigStruct2() nounwind readnone { +; Structs of more than 4 words are partially returned in memory so long as the +; function is not variadic. +define { i32, i32, i32, i32, i32} @f(i32, i32, i32, i32, i32) nounwind readnone { +; CHECK-LABEL: f: +; CHECK: ldc [[REGISTER:r[0-9]+]], 5 +; CHECK-NEXT: stw [[REGISTER]], sp[2] +; CHECK-NEXT: retsp 0 +body: + ret { i32, i32, i32, i32, i32} { i32 undef, i32 undef, i32 undef, i32 undef, i32 5} +} + +@x = external global i32 +@y = external global i32 + +; Check we call a function returning more than 4 words correctly. +define i32 @g() nounwind { +; CHECK-LABEL: g: +; CHECK: entsp 3 +; CHECK: ldc [[REGISTER:r[0-9]+]], 0 +; CHECK: stw [[REGISTER]], sp[1] +; CHECK: bl f +; CHECK-NEXT: ldw r0, sp[2] +; CHECK-NEXT: retsp 3 +; +body: + %0 = call { i32, i32, i32, i32, i32 } @f(i32 0, i32 0, i32 0, i32 0, i32 0) + %1 = extractvalue { i32, i32, i32, i32, i32 } %0, 4 + ret i32 %1 +} + +; Variadic functions return structs bigger than 4 words via a hidden +; sret-parameter +define internal %1 @ReturnBigStruct2(i32 %dummy, ...) nounwind readnone { entry: %0 = insertvalue %1 zeroinitializer, i32 12, 0 %1 = insertvalue %1 %0, i32 24, 1 diff --git a/test/CodeGen/XCore/byVal.ll b/test/CodeGen/XCore/byVal.ll index e9612fd6021a..df6c6d351d18 100644 --- a/test/CodeGen/XCore/byVal.ll +++ b/test/CodeGen/XCore/byVal.ll @@ -20,7 +20,7 @@ entry: ; CHECK: ldaw r5, sp[1] ; CHECK: ldc r2, 40 ; CHECK: mov r0, r5 -; CHECK: bl memcpy +; CHECK: bl __memcpy_4 ; CHECK: mov r0, r5 ; CHECK: bl f1 ; CHECK: mov r0, r4 diff --git a/test/CodeGen/XCore/call.ll b/test/CodeGen/XCore/call.ll new file mode 100644 index 000000000000..06a12f144405 --- /dev/null +++ b/test/CodeGen/XCore/call.ll @@ -0,0 +1,10 @@ +; RUN: llc < %s -march=xcore | FileCheck %s + +; CHECK-LABEL: bl_imm: +; CHECK: ldw [[R0:r[0-9]+]], cp +; CHECK: bla [[R0]] +define void @bl_imm() nounwind { +entry: + tail call void inttoptr (i64 65536 to void ()*)() nounwind + ret void +} diff --git a/test/CodeGen/XCore/codemodel.ll b/test/CodeGen/XCore/codemodel.ll new file mode 100644 index 000000000000..0245893c478d --- /dev/null +++ b/test/CodeGen/XCore/codemodel.ll @@ -0,0 +1,213 @@ + +; RUN: not llc < %s -march=xcore -code-model=medium 2>&1 | FileCheck %s -check-prefix=BAD_CM +; RUN: not llc < %s -march=xcore -code-model=kernel 2>&1 | FileCheck %s -check-prefix=BAD_CM +; BAD_CM: Target only supports CodeModel Small or Large + + +; RUN: llc < %s -march=xcore -code-model=default | FileCheck %s +; RUN: llc < %s -march=xcore -code-model=small | FileCheck %s +; RUN: llc < %s -march=xcore -code-model=large | FileCheck %s -check-prefix=LARGE + + +; CHECK-LABEL: test: +; CHECK: zext r0, 1 +; CHECK: bt r0, [[JUMP:.LBB[0-9_]*]] +; CHECK: ldaw r0, dp[A2] +; CHECK: retsp 0 +; CHECK: [[JUMP]] +; CHECK: ldaw r0, dp[A1] +; CHECK: retsp 0 +; LARGE-LABEL: test: +; LARGE: zext r0, 1 +; LARGE: ldaw r11, cp[.LCPI{{[0-9_]*}}] +; LARGE: mov r1, r11 +; LARGE: ldaw r11, cp[.LCPI{{[0-9_]*}}] +; LARGE: bt r0, [[JUMP:.LBB[0-9_]*]] +; LARGE: mov r11, r1 +; LARGE: [[JUMP]] +; LARGE: ldw r0, r11[0] +; LARGE: retsp 0 +@A1 = external global [50000 x i32] +@A2 = external global [50000 x i32] +define [50000 x i32]* @test(i1 %bool) nounwind { +entry: + %Addr = select i1 %bool, [50000 x i32]* @A1, [50000 x i32]* @A2 + ret [50000 x i32]* %Addr +} + + +; CHECK: .section .cp.rodata.cst4,"aMc",@progbits,4 +; CHECK: .long 65536 +; CHECK: .text +; CHECK-LABEL: f: +; CHECK: ldc r1, 65532 +; CHECK: add r1, r0, r1 +; CHECK: ldw r1, r1[0] +; CHECK: ldw r2, cp[.LCPI{{[0-9_]*}}] +; CHECK: add r0, r0, r2 +; CHECK: ldw r0, r0[0] +; CHECK: add r0, r1, r0 +; CHECK: ldw r1, dp[l] +; CHECK: add r0, r0, r1 +; CHECK: ldw r1, dp[l+4] +; CHECK: add r0, r0, r1 +; CHECK: ldw r1, dp[l+392] +; CHECK: add r0, r0, r1 +; CHECK: ldw r1, dp[l+396] +; CHECK: add r0, r0, r1 +; CHECK: ldw r1, dp[s] +; CHECK: add r0, r0, r1 +; CHECK: ldw r1, dp[s+36] +; CHECK: add r0, r0, r1 +; CHECK: retsp 0 +; +; LARGE: .section .cp.rodata.cst4,"aMc",@progbits,4 +; LARGE: .long 65536 +; LARGE: .section .cp.rodata,"ac",@progbits +; LARGE: .long l +; LARGE: .long l+4 +; LARGE: .long l+392 +; LARGE: .long l+396 +; LARGE: .text +; LARGE-LABEL: f: +; LARGE: ldc r1, 65532 +; LARGE: add r1, r0, r1 +; LARGE: ldw r1, r1[0] +; LARGE: ldw r2, cp[.LCPI{{[0-9_]*}}] +; LARGE: add r0, r0, r2 +; LARGE: ldw r0, r0[0] +; LARGE: add r0, r1, r0 +; LARGE: ldw r1, cp[.LCPI{{[0-9_]*}}] +; LARGE: ldw r1, r1[0] +; LARGE: add r0, r0, r1 +; LARGE: ldw r1, cp[.LCPI{{[0-9_]*}}] +; LARGE: ldw r1, r1[0] +; LARGE: add r0, r0, r1 +; LARGE: ldw r1, cp[.LCPI{{[0-9_]*}}] +; LARGE: ldw r1, r1[0] +; LARGE: add r0, r0, r1 +; LARGE: ldw r1, cp[.LCPI{{[0-9_]*}}] +; LARGE: ldw r1, r1[0] +; LARGE: add r0, r0, r1 +; LARGE: ldw r1, dp[s] +; LARGE: add r0, r0, r1 +; LARGE: ldw r1, dp[s+36] +; LARGE: add r0, r0, r1 +; LARGE: retsp 0 +define i32 @f(i32* %i) { +entry: + %0 = getelementptr inbounds i32* %i, i32 16383 + %1 = load i32* %0 + %2 = getelementptr inbounds i32* %i, i32 16384 + %3 = load i32* %2 + %4 = add nsw i32 %1, %3 + %5 = load i32* getelementptr inbounds ([100 x i32]* @l, i32 0, i32 0) + %6 = add nsw i32 %4, %5 + %7 = load i32* getelementptr inbounds ([100 x i32]* @l, i32 0, i32 1) + %8 = add nsw i32 %6, %7 + %9 = load i32* getelementptr inbounds ([100 x i32]* @l, i32 0, i32 98) + %10 = add nsw i32 %8, %9 + %11 = load i32* getelementptr inbounds ([100 x i32]* @l, i32 0, i32 99) + %12 = add nsw i32 %10, %11 + %13 = load i32* getelementptr inbounds ([10 x i32]* @s, i32 0, i32 0) + %14 = add nsw i32 %12, %13 + %15 = load i32* getelementptr inbounds ([10 x i32]* @s, i32 0, i32 9) + %16 = add nsw i32 %14, %15 + ret i32 %16 +} + + +; CHECK-LABEL: UnknownSize: +; CHECK: ldw r0, dp[NoSize+40] +; CHECK-NEXT: retsp 0 +; +; LARGE: .section .cp.rodata,"ac",@progbits +; LARGE: .LCPI{{[0-9_]*}} +; LARGE-NEXT: .long NoSize +; LARGE-NEXT: .text +; LARGE-LABEL: UnknownSize: +; LARGE: ldw r0, cp[.LCPI{{[0-9_]*}}] +; LARGE-NEXT: ldw r0, r0[0] +; LARGE-NEXT: retsp 0 +@NoSize = external global [0 x i32] +define i32 @UnknownSize() nounwind { +entry: + %0 = load i32* getelementptr inbounds ([0 x i32]* @NoSize, i32 0, i32 10) + ret i32 %0 +} + + +; CHECK-LABEL: UnknownStruct: +; CHECK: ldaw r0, dp[Unknown] +; CHECK-NEXT: retsp 0 +; +; LARGE: .section .cp.rodata,"ac",@progbits +; LARGE: .LCPI{{[0-9_]*}} +; LARGE-NEXT: .long Unknown +; LARGE-NEXT: .text +; LARGE-LABEL: UnknownStruct: +; LARGE: ldw r0, cp[.LCPI{{[0-9_]*}}] +; LARGE-NEXT: retsp 0 +%Struct = type opaque +@Unknown = external global %Struct +define %Struct* @UnknownStruct() nounwind { +entry: + ret %Struct* @Unknown +} + + +; CHECK: .section .dp.bss,"awd",@nobits +; CHECK-LABEL: l: +; CHECK: .space 400 +; LARGE: .section .dp.bss.large,"awd",@nobits +; LARGE-LABEL: l: +; LARGE: .space 400 +@l = global [100 x i32] zeroinitializer + +; CHECK-LABEL: s: +; CHECK: .space 40 +; LARGE: .section .dp.bss,"awd",@nobits +; LARGE-LABEL: s: +; LARGE: .space 40 +@s = global [10 x i32] zeroinitializer + +; CHECK: .section .dp.rodata,"awd",@progbits +; CHECK-LABEL: cl: +; CHECK: .space 400 +; LARGE: .section .dp.rodata.large,"awd",@progbits +; LARGE-LABEL: cl: +; LARGE: .space 400 +@cl = constant [100 x i32] zeroinitializer + +; CHECK-LABEL: cs: +; CHECK: .space 40 +; LARGE: .section .dp.rodata,"awd",@progbits +; LARGE-LABEL: cs: +; LARGE: .space 40 +@cs = constant [10 x i32] zeroinitializer + +; CHECK: .section .cp.rodata,"ac",@progbits +; CHECK-LABEL: icl: +; CHECK: .space 400 +; LARGE: .section .cp.rodata.large,"ac",@progbits +; LARGE-LABEL: icl: +; LARGE: .space 400 +@icl = internal constant [100 x i32] zeroinitializer + +; CHECK-LABEL: cs: +; CHECK: .space 40 +; LARGE: .section .cp.rodata,"ac",@progbits +; LARGE-LABEL: cs: +; LARGE: .space 40 +@ics = internal constant [10 x i32] zeroinitializer + +; CHECK: .section .cp.namedsection,"ac",@progbits +; CHECK-LABEL: cpsec: +; CHECK: .long 0 +@cpsec = constant i32 0, section ".cp.namedsection" + +; CHECK: .section .dp.namedsection,"awd",@progbits +; CHECK-LABEL: dpsec: +; CHECK: .long 0 +@dpsec = global i32 0, section ".dp.namedsection" + diff --git a/test/CodeGen/XCore/dwarf_debug.ll b/test/CodeGen/XCore/dwarf_debug.ll new file mode 100644 index 000000000000..2f4b23111bb2 --- /dev/null +++ b/test/CodeGen/XCore/dwarf_debug.ll @@ -0,0 +1,39 @@ +; RUN: llc < %s -mtriple=xcore-unknown-unknown -O0 | FileCheck %s + +; target datalayout = "e-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-i64:32-f64:32-a:0:32-n32" +; target triple = "xcore" + +; CHECK-LABEL: f +; CHECK: entsp 2 +; ...the prologue... +; CHECK: .loc 1 2 0 prologue_end # :2:0 +; CHECK: add r0, r0, 1 +; CHECK: retsp 2 +define i32 @f(i32 %a) { +entry: + %a.addr = alloca i32, align 4 + store i32 %a, i32* %a.addr, align 4 + call void @llvm.dbg.declare(metadata !{i32* %a.addr}, metadata !11), !dbg !12 + %0 = load i32* %a.addr, align 4, !dbg !12 + %add = add nsw i32 %0, 1, !dbg !12 + ret i32 %add, !dbg !12 +} + +declare void @llvm.dbg.declare(metadata, metadata) + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!9, !10} +!0 = metadata !{i32 786449, metadata !1, i32 12, metadata !"", i1 false, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, metadata !2, metadata !2, metadata !"", i32 1} +!1 = metadata !{metadata !"", metadata !""} +!2 = metadata !{} +!3 = metadata !{metadata !4} +!4 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"f", metadata !"f", metadata !"", i32 2, metadata !6, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, i32 (i32)* @f, null, null, metadata !2, i32 2} +!5 = metadata !{i32 786473, metadata !1} +!6 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !7, i32 0, null, null, null} +!7 = metadata !{metadata !8, metadata !8} +!8 = metadata !{i32 786468, null, null, metadata !"int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} +!9 = metadata !{i32 2, metadata !"Dwarf Version", i32 4} +!10 = metadata !{i32 2, metadata !"Debug Info Version", i32 1} +!11 = metadata !{i32 786689, metadata !4, metadata !"a", metadata !5, i32 16777218, metadata !8, i32 0, i32 0} +!12 = metadata !{i32 2, i32 0, metadata !4, null} + diff --git a/test/CodeGen/XCore/epilogue_prologue.ll b/test/CodeGen/XCore/epilogue_prologue.ll index 185565f4e287..99978145ed36 100644 --- a/test/CodeGen/XCore/epilogue_prologue.ll +++ b/test/CodeGen/XCore/epilogue_prologue.ll @@ -1,5 +1,20 @@ ; RUN: llc < %s -march=xcore | FileCheck %s +; RUN: llc < %s -march=xcore -disable-fp-elim | FileCheck %s -check-prefix=CHECKFP +; When using SP for small frames, we don't need any scratch registers (SR). +; When using SP for large frames, we may need two scratch registers. +; When using FP, for large or small frames, we may need one scratch register. + +; FP + small frame: spill FP+SR = entsp 2 +; CHECKFP-LABEL: f1 +; CHECKFP: entsp 2 +; CHECKFP-NEXT: stw r10, sp[1] +; CHECKFP-NEXT: ldaw r10, sp[0] +; CHECKFP: set sp, r10 +; CHECKFP-NEXT: ldw r10, sp[1] +; CHECKFP-NEXT: retsp 2 +; +; !FP + small frame: no spills = no stack adjustment needed ; CHECK-LABEL: f1 ; CHECK: stw lr, sp[0] ; CHECK: ldw lr, sp[0] @@ -10,17 +25,239 @@ entry: ret void } + +; FP + small frame: spill FP+SR+R0+LR = entsp 3 + extsp 1 +; CHECKFP-LABEL:f3 +; CHECKFP: entsp 3 +; CHECKFP-NEXT: stw r10, sp[1] +; CHECKFP-NEXT: ldaw r10, sp[0] +; CHECKFP-NEXT: stw [[REG:r[4-9]+]], r10[2] +; CHECKFP-NEXT: mov [[REG]], r0 +; CHECKFP-NEXT: extsp 1 +; CHECKFP-NEXT: bl f2 +; CHECKFP-NEXT: ldaw sp, sp[1] +; CHECKFP-NEXT: mov r0, [[REG]] +; CHECKFP-NEXT: ldw [[REG]], r10[2] +; CHECKFP-NEXT: set sp, r10 +; CHECKFP-NEXT: ldw r10, sp[1] +; CHECKFP-NEXT: retsp 3 +; +; !FP + small frame: spill R0+LR = entsp 2 ; CHECK-LABEL: f3 ; CHECK: entsp 2 -; CHECK: stw [[REG:r[4-9]+]], sp[1] -; CHECK: mov [[REG]], r0 -; CHECK: bl f2 -; CHECK: mov r0, [[REG]] -; CHECK: ldw [[REG]], sp[1] -; CHECK: retsp 2 +; CHECK-NEXT: stw [[REG:r[4-9]+]], sp[1] +; CHECK-NEXT: mov [[REG]], r0 +; CHECK-NEXT: bl f2 +; CHECK-NEXT: mov r0, [[REG]] +; CHECK-NEXT: ldw [[REG]], sp[1] +; CHECK-NEXT: retsp 2 declare void @f2() define i32 @f3(i32 %i) nounwind { entry: call void @f2() ret i32 %i } + + +; FP + large frame: spill FP+SR = entsp 2 + 100000 +; CHECKFP-LABEL: f4 +; CHECKFP: entsp 65535 +; CHECKFP-NEXT: .Ltmp{{[0-9]+}} +; CHECKFP-NEXT: .cfi_def_cfa_offset 262140 +; CHECKFP-NEXT: .Ltmp{{[0-9]+}} +; CHECKFP-NEXT: .cfi_offset 15, 0 +; CHECKFP-NEXT: extsp 34467 +; CHECKFP-NEXT: .Ltmp{{[0-9]+}} +; CHECKFP-NEXT: .cfi_def_cfa_offset 400008 +; CHECKFP-NEXT: stw r10, sp[1] +; CHECKFP-NEXT: .Ltmp{{[0-9]+}} +; CHECKFP-NEXT: .cfi_offset 10, -400004 +; CHECKFP-NEXT: ldaw r10, sp[0] +; CHECKFP-NEXT: .Ltmp{{[0-9]+}} +; CHECKFP-NEXT: .cfi_def_cfa_register 10 +; CHECKFP-NEXT: set sp, r10 +; CHECKFP-NEXT: ldw r10, sp[1] +; CHECKFP-NEXT: ldaw sp, sp[65535] +; CHECKFP-NEXT: retsp 34467 +; +; !FP + large frame: spill SR+SR = entsp 2 + 100000 +; CHECK-LABEL: f4 +; CHECK: entsp 65535 +; CHECK-NEXT: .Ltmp{{[0-9]+}} +; CHECK-NEXT: .cfi_def_cfa_offset 262140 +; CHECK-NEXT: .Ltmp{{[0-9]+}} +; CHECK-NEXT: .cfi_offset 15, 0 +; CHECK-NEXT: extsp 34467 +; CHECK-NEXT: .Ltmp{{[0-9]+}} +; CHECK-NEXT: .cfi_def_cfa_offset 400008 +; CHECK-NEXT: ldaw sp, sp[65535] +; CHECK-NEXT: retsp 34467 +define void @f4() { +entry: + %0 = alloca [100000 x i32] + ret void +} + + +; FP + large frame: spill FP+SR+R4+LR = entsp 3 + 200000 + extsp 1 +; CHECKFP: .section .cp.rodata.cst4,"aMc",@progbits,4 +; CHECKFP-NEXT: .align 4 +; CHECKFP-NEXT: .LCPI[[CNST0:[0-9_]+]]: +; CHECKFP-NEXT: .long 200002 +; CHECKFP-NEXT: .LCPI[[CNST1:[0-9_]+]]: +; CHECKFP-NEXT: .long 200001 +; CHECKFP-NEXT: .text +; CHECKFP-LABEL: f6 +; CHECKFP: entsp 65535 +; CHECKFP-NEXT: .Ltmp{{[0-9]+}} +; CHECKFP-NEXT: .cfi_def_cfa_offset 262140 +; CHECKFP-NEXT: .Ltmp{{[0-9]+}} +; CHECKFP-NEXT: .cfi_offset 15, 0 +; CHECKFP-NEXT: extsp 65535 +; CHECKFP-NEXT: .Ltmp{{[0-9]+}} +; CHECKFP-NEXT: .cfi_def_cfa_offset 524280 +; CHECKFP-NEXT: extsp 65535 +; CHECKFP-NEXT: .Ltmp{{[0-9]+}} +; CHECKFP-NEXT: .cfi_def_cfa_offset 786420 +; CHECKFP-NEXT: extsp 3398 +; CHECKFP-NEXT: .Ltmp{{[0-9]+}} +; CHECKFP-NEXT: .cfi_def_cfa_offset 800012 +; CHECKFP-NEXT: stw r10, sp[1] +; CHECKFP-NEXT: .Ltmp{{[0-9]+}} +; CHECKFP-NEXT: .cfi_offset 10, -800008 +; CHECKFP-NEXT: ldaw r10, sp[0] +; CHECKFP-NEXT: .Ltmp{{[0-9]+}} +; CHECKFP-NEXT: .cfi_def_cfa_register 10 +; CHECKFP-NEXT: ldw r1, cp[.LCPI[[CNST0]]] +; CHECKFP-NEXT: stw [[REG:r[4-9]+]], r10[r1] +; CHECKFP-NEXT: .Ltmp{{[0-9]+}} +; CHECKFP-NEXT: .cfi_offset 4, -4 +; CHECKFP-NEXT: mov [[REG]], r0 +; CHECKFP-NEXT: extsp 1 +; CHECKFP-NEXT: ldaw r0, r10[2] +; CHECKFP-NEXT: bl f5 +; CHECKFP-NEXT: ldaw sp, sp[1] +; CHECKFP-NEXT: ldw r1, cp[.LCPI3_1] +; CHECKFP-NEXT: ldaw r0, r10[r1] +; CHECKFP-NEXT: extsp 1 +; CHECKFP-NEXT: bl f5 +; CHECKFP-NEXT: ldaw sp, sp[1] +; CHECKFP-NEXT: mov r0, [[REG]] +; CHECKFP-NEXT: ldw r1, cp[.LCPI[[CNST0]]] +; CHECKFP-NEXT: ldw [[REG]], r10[r1] +; CHECKFP-NEXT: set sp, r10 +; CHECKFP-NEXT: ldw r10, sp[1] +; CHECKFP-NEXT: ldaw sp, sp[65535] +; CHECKFP-NEXT: ldaw sp, sp[65535] +; CHECKFP-NEXT: ldaw sp, sp[65535] +; CHECKFP-NEXT: retsp 3398 +; +; !FP + large frame: spill SR+SR+R4+LR = entsp 4 + 200000 +; CHECK: .section .cp.rodata.cst4,"aMc",@progbits,4 +; CHECK-NEXT: .align 4 +; CHECK-NEXT: .LCPI[[CNST0:[0-9_]+]]: +; CHECK-NEXT: .long 200003 +; CHECK-NEXT: .LCPI[[CNST1:[0-9_]+]]: +; CHECK-NEXT: .long 200002 +; CHECK-NEXT: .text +; CHECK-LABEL: f6 +; CHECK: entsp 65535 +; CHECK-NEXT: .Ltmp{{[0-9]+}} +; CHECK-NEXT: .cfi_def_cfa_offset 262140 +; CHECK-NEXT: .Ltmp{{[0-9]+}} +; CHECK-NEXT: .cfi_offset 15, 0 +; CHECK-NEXT: extsp 65535 +; CHECK-NEXT: .Ltmp{{[0-9]+}} +; CHECK-NEXT: .cfi_def_cfa_offset 524280 +; CHECK-NEXT: extsp 65535 +; CHECK-NEXT: .Ltmp{{[0-9]+}} +; CHECK-NEXT: .cfi_def_cfa_offset 786420 +; CHECK-NEXT: extsp 3399 +; CHECK-NEXT: .Ltmp{{[0-9]+}} +; CHECK-NEXT: .cfi_def_cfa_offset 800016 +; CHECK-NEXT: ldaw r1, sp[0] +; CHECK-NEXT: ldw r2, cp[.LCPI[[CNST0]]] +; CHECK-NEXT: stw [[REG:r[4-9]+]], r1[r2] +; CHECK-NEXT: .Ltmp{{[0-9]+}} +; CHECK-NEXT: .cfi_offset 4, -4 +; CHECK-NEXT: mov [[REG]], r0 +; CHECK-NEXT: ldaw r0, sp[3] +; CHECK-NEXT: bl f5 +; CHECK-NEXT: ldaw r0, sp[0] +; CHECK-NEXT: ldw r1, cp[.LCPI[[CNST1]]] +; CHECK-NEXT: ldaw r0, r0[r1] +; CHECK-NEXT: bl f5 +; CHECK-NEXT: mov r0, [[REG]] +; CHECK-NEXT: ldaw [[REG]], sp[0] +; CHECK-NEXT: ldw r1, cp[.LCPI[[CNST0]]] +; CHECK-NEXT: ldw [[REG]], [[REG]][r1] +; CHECK-NEXT: ldaw sp, sp[65535] +; CHECK-NEXT: ldaw sp, sp[65535] +; CHECK-NEXT: ldaw sp, sp[65535] +; CHECK-NEXT: retsp 3399 +declare void @f5(i32*) +define i32 @f6(i32 %i) { +entry: + %0 = alloca [200000 x i32] + %1 = getelementptr inbounds [200000 x i32]* %0, i32 0, i32 0 + call void @f5(i32* %1) + %2 = getelementptr inbounds [200000 x i32]* %0, i32 0, i32 199999 + call void @f5(i32* %2) + ret i32 %i +} + +; FP + large frame: spill FP+SR+LR = entsp 2 + 256 + extsp 1 +; CHECKFP-LABEL:f8 +; CHECKFP: entsp 258 +; CHECKFP-NEXT: stw r10, sp[1] +; CHECKFP-NEXT: ldaw r10, sp[0] +; CHECKFP-NEXT: mkmsk [[REG:r[0-9]+]], 8 +; CHECKFP-NEXT: ldaw r0, r10{{\[}}[[REG]]{{\]}} +; CHECKFP-NEXT: extsp 1 +; CHECKFP-NEXT: bl f5 +; CHECKFP-NEXT: ldaw sp, sp[1] +; CHECKFP-NEXT: set sp, r10 +; CHECKFP-NEXT: ldw r10, sp[1] +; CHECKFP-NEXT: retsp 258 +; +; !FP + large frame: spill SR+SR+LR = entsp 3 + 256 +; CHECK-LABEL:f8 +; CHECK: entsp 257 +; CHECK-NEXT: ldaw r0, sp[254] +; CHECK-NEXT: bl f5 +; CHECK-NEXT: retsp 257 +define void @f8() nounwind { +entry: + %0 = alloca [256 x i32] + %1 = getelementptr inbounds [256 x i32]* %0, i32 0, i32 253 + call void @f5(i32* %1) + ret void +} + +; FP + large frame: spill FP+SR+LR = entsp 2 + 32768 + extsp 1 +; CHECKFP-LABEL:f9 +; CHECKFP: entsp 32770 +; CHECKFP-NEXT: stw r10, sp[1] +; CHECKFP-NEXT: ldaw r10, sp[0] +; CHECKFP-NEXT: ldc [[REG:r[0-9]+]], 32767 +; CHECKFP-NEXT: ldaw r0, r10{{\[}}[[REG]]{{\]}} +; CHECKFP-NEXT: extsp 1 +; CHECKFP-NEXT: bl f5 +; CHECKFP-NEXT: ldaw sp, sp[1] +; CHECKFP-NEXT: set sp, r10 +; CHECKFP-NEXT: ldw r10, sp[1] +; CHECKFP-NEXT: retsp 32770 +; +; !FP + large frame: spill SR+SR+LR = entsp 3 + 32768 +; CHECK-LABEL:f9 +; CHECK: entsp 32771 +; CHECK-NEXT: ldaw r0, sp[32768] +; CHECK-NEXT: bl f5 +; CHECK-NEXT: retsp 32771 +define void @f9() nounwind { +entry: + %0 = alloca [32768 x i32] + %1 = getelementptr inbounds [32768 x i32]* %0, i32 0, i32 32765 + call void @f5(i32* %1) + ret void +} diff --git a/test/CodeGen/XCore/exception.ll b/test/CodeGen/XCore/exception.ll index 8018cdcada7a..3179fcdfcf5d 100644 --- a/test/CodeGen/XCore/exception.ll +++ b/test/CodeGen/XCore/exception.ll @@ -29,9 +29,8 @@ entry: ; CHECK: .cfi_offset 15, 0 ; CHECK: ldc r0, 4 ; CHECK: bl __cxa_allocate_exception -; CHECK: ldaw r11, cp[_ZTIi] +; CHECK: ldaw r1, dp[_ZTIi] ; CHECK: ldc r2, 0 -; CHECK: mov r1, r11 ; CHECK: bl __cxa_throw define void @fn_throw() { entry: diff --git a/test/CodeGen/XCore/globals.ll b/test/CodeGen/XCore/globals.ll index b3a872bb6892..04e135c25cae 100644 --- a/test/CodeGen/XCore/globals.ll +++ b/test/CodeGen/XCore/globals.ll @@ -17,11 +17,18 @@ entry: define i32 *@addr_G3() { entry: ; CHECK-LABEL: addr_G3: -; CHECK: ldaw r11, cp[G3] -; CHECK: mov r0, r11 +; CHECK: ldaw r0, dp[G3] ret i32* @G3 } +define i32 *@addr_iG3() { +entry: +; CHECK-LABEL: addr_iG3: +; CHECK: ldaw r11, cp[iG3] +; CHECK: mov r0, r11 + ret i32* @iG3 +} + define i32 **@addr_G4() { entry: ; CHECK-LABEL: addr_G4: @@ -32,11 +39,18 @@ entry: define i32 **@addr_G5() { entry: ; CHECK-LABEL: addr_G5: -; CHECK: ldaw r11, cp[G5] -; CHECK: mov r0, r11 +; CHECK: ldaw r0, dp[G5] ret i32** @G5 } +define i32 **@addr_iG5() { +entry: +; CHECK-LABEL: addr_iG5: +; CHECK: ldaw r11, cp[iG5] +; CHECK: mov r0, r11 + ret i32** @iG5 +} + define i32 **@addr_G6() { entry: ; CHECK-LABEL: addr_G6: @@ -47,11 +61,18 @@ entry: define i32 **@addr_G7() { entry: ; CHECK-LABEL: addr_G7: -; CHECK: ldaw r11, cp[G7] -; CHECK: mov r0, r11 +; CHECK: ldaw r0, dp[G7] ret i32** @G7 } +define i32 **@addr_iG7() { +entry: +; CHECK-LABEL: addr_iG7: +; CHECK: ldaw r11, cp[iG7] +; CHECK: mov r0, r11 + ret i32** @iG7 +} + define i32 *@addr_G8() { entry: ; CHECK-LABEL: addr_G8: @@ -68,26 +89,38 @@ entry: ; CHECK: G2: @G3 = unnamed_addr constant i32 9401 -; CHECK: .section .cp.rodata.cst4,"aMc",@progbits,4 +; CHECK: .section .dp.rodata,"awd",@progbits ; CHECK: G3: +@iG3 = internal constant i32 9401 +; CHECK: .section .cp.rodata,"ac",@progbits +; CHECK: iG3: + @G4 = global i32* @G1 ; CHECK: .section .dp.data,"awd",@progbits ; CHECK: G4: @G5 = unnamed_addr constant i32* @G1 -; CHECK: .section .cp.rodata,"ac",@progbits +; CHECK: .section .dp.rodata,"awd",@progbits ; CHECK: G5: +@iG5 = internal unnamed_addr constant i32* @G1 +; CHECK: .section .cp.rodata,"ac",@progbits +; CHECK: iG5: + @G6 = global i32* @G8 ; CHECK: .section .dp.data,"awd",@progbits ; CHECK: G6: @G7 = unnamed_addr constant i32* @G8 -; CHECK: .section .cp.rodata,"ac",@progbits +; CHECK: .section .dp.rodata,"awd",@progbits ; CHECK: G7: -@G8 = internal global i32 9312 +@iG7 = internal unnamed_addr constant i32* @G8 +; CHECK: .section .cp.rodata,"ac",@progbits +; CHECK: iG7: + +@G8 = global i32 9312 ; CHECK: .section .dp.data,"awd",@progbits ; CHECK: G8: diff --git a/test/CodeGen/XCore/inline-asm.ll b/test/CodeGen/XCore/inline-asm.ll index af3edd1544a2..e9f5b5769997 100644 --- a/test/CodeGen/XCore/inline-asm.ll +++ b/test/CodeGen/XCore/inline-asm.ll @@ -30,3 +30,24 @@ entry: tail call void asm sideeffect "foo ${0:n}", "i"(i32 99) nounwind ret void } + +@x = external global i32 +@y = external global i32, section ".cp.rodata" + +; CHECK-LABEL: f5: +; CHECK: ldw r0, dp[x] +; CHECK: retsp 0 +define i32 @f5() nounwind { +entry: + %asmtmp = call i32 asm "ldw $0, $1", "=r,*m"(i32* @x) nounwind + ret i32 %asmtmp +} + +; CHECK-LABEL: f6: +; CHECK: ldw r0, cp[y] +; CHECK: retsp 0 +define i32 @f6() nounwind { +entry: + %asmtmp = call i32 asm "ldw $0, $1", "=r,*m"(i32* @y) nounwind + ret i32 %asmtmp +} diff --git a/test/CodeGen/XCore/linkage.ll b/test/CodeGen/XCore/linkage.ll index 7a1179b7ab6e..7384fe7bcf09 100644 --- a/test/CodeGen/XCore/linkage.ll +++ b/test/CodeGen/XCore/linkage.ll @@ -25,9 +25,21 @@ define protected void @test_protected() { ; CHECK: .weak array @array = weak global [2 x i32] zeroinitializer +; CHECK: .globl ac.globound +; CHECK: ac.globound = 2 +; CHECK: .weak ac.globound +; CHECK: .globl ac +; CHECK: .weak ac +@ac = common global [2 x i32] zeroinitializer + +; CHECK: .globl gd ; CHECK: .weak gd @gd = weak global i32 0 +; CHECK: .globl gc +; CHECK: .weak gc +@gc = common global i32 0 + ; CHECK-NOT: .hidden test_hidden_declaration ; CHECK: .weak gr diff --git a/test/CodeGen/XCore/lit.local.cfg b/test/CodeGen/XCore/lit.local.cfg index 3e84c1befeab..0b947bbbb850 100644 --- a/test/CodeGen/XCore/lit.local.cfg +++ b/test/CodeGen/XCore/lit.local.cfg @@ -1,4 +1,3 @@ -targets = set(config.root.targets_to_build.split()) -if not 'XCore' in targets: +if not 'XCore' in config.root.targets: config.unsupported = True diff --git a/test/CodeGen/XCore/llvm-intrinsics.ll b/test/CodeGen/XCore/llvm-intrinsics.ll new file mode 100644 index 000000000000..b436282615c2 --- /dev/null +++ b/test/CodeGen/XCore/llvm-intrinsics.ll @@ -0,0 +1,361 @@ +; RUN: llc < %s -march=xcore | FileCheck %s +; RUN: llc < %s -march=xcore -disable-fp-elim | FileCheck %s -check-prefix=CHECKFP + +declare i8* @llvm.frameaddress(i32) nounwind readnone +declare i8* @llvm.returnaddress(i32) nounwind +declare i8* @llvm.eh.dwarf.cfa(i32) nounwind +declare void @llvm.eh.return.i32(i32, i8*) nounwind +declare void @llvm.eh.unwind.init() nounwind + +define i8* @FA0() nounwind { +entry: +; CHECK-LABEL: FA0 +; CHECK: ldaw r0, sp[0] +; CHECK-NEXT: retsp 0 + %0 = call i8* @llvm.frameaddress(i32 0) + ret i8* %0 +} + +define i8* @FA1() nounwind { +entry: +; CHECK-LABEL: FA1 +; CHECK: entsp 100 +; CHECK-NEXT: ldaw r0, sp[0] +; CHECK-NEXT: retsp 100 + %0 = alloca [100 x i32] + %1 = call i8* @llvm.frameaddress(i32 0) + ret i8* %1 +} + +define i8* @RA0() nounwind { +entry: +; CHECK-LABEL: RA0 +; CHECK: stw lr, sp[0] +; CHECK-NEXT: ldw r0, sp[0] +; CHECK-NEXT: ldw lr, sp[0] +; CHECK-NEXT: retsp 0 + %0 = call i8* @llvm.returnaddress(i32 0) + ret i8* %0 +} + +define i8* @RA1() nounwind { +entry: +; CHECK-LABEL: RA1 +; CHECK: entsp 100 +; CHECK-NEXT: ldw r0, sp[100] +; CHECK-NEXT: retsp 100 + %0 = alloca [100 x i32] + %1 = call i8* @llvm.returnaddress(i32 0) + ret i8* %1 +} + +; test FRAME_TO_ARGS_OFFSET lowering +define i8* @FTAO0() nounwind { +entry: +; CHECK-LABEL: FTAO0 +; CHECK: ldc r0, 0 +; CHECK-NEXT: ldaw r1, sp[0] +; CHECK-NEXT: add r0, r1, r0 +; CHECK-NEXT: retsp 0 + %0 = call i8* @llvm.eh.dwarf.cfa(i32 0) + ret i8* %0 +} + +define i8* @FTAO1() nounwind { +entry: +; CHECK-LABEL: FTAO1 +; CHECK: entsp 100 +; CHECK-NEXT: ldc r0, 400 +; CHECK-NEXT: ldaw r1, sp[0] +; CHECK-NEXT: add r0, r1, r0 +; CHECK-NEXT: retsp 100 + %0 = alloca [100 x i32] + %1 = call i8* @llvm.eh.dwarf.cfa(i32 0) + ret i8* %1 +} + +define i8* @EH0(i32 %offset, i8* %handler) { +entry: +; CHECK-LABEL: EH0 +; CHECK: entsp 2 +; CHECK: .cfi_def_cfa_offset 8 +; CHECK: .cfi_offset 15, 0 +; CHECK: .cfi_offset 1, -8 +; CHECK: .cfi_offset 0, -4 +; CHECK: ldc r2, 8 +; CHECK-NEXT: ldaw r3, sp[0] +; CHECK-NEXT: add r2, r3, r2 +; CHECK-NEXT: add r2, r2, r0 +; CHECK-NEXT: mov r3, r1 +; CHECK-NEXT: ldw r1, sp[0] +; CHECK-NEXT: ldw r0, sp[1] +; CHECK-NEXT: set sp, r2 +; CHECK-NEXT: bau r3 + call void @llvm.eh.return.i32(i32 %offset, i8* %handler) + unreachable +} + +declare void @foo(...) +define i8* @EH1(i32 %offset, i8* %handler) { +entry: +; CHECK-LABEL: EH1 +; CHECK: entsp 5 +; CHECK: .cfi_def_cfa_offset 20 +; CHECK: .cfi_offset 15, 0 +; CHECK: .cfi_offset 1, -16 +; CHECK: .cfi_offset 0, -12 +; CHECK: stw r4, sp[4] +; CHECK: .cfi_offset 4, -4 +; CHECK: stw r5, sp[3] +; CHECK: .cfi_offset 5, -8 +; CHECK: mov r4, r1 +; CHECK-NEXT: mov r5, r0 +; CHECK-NEXT: bl foo +; CHECK-NEXT: ldc r0, 20 +; CHECK-NEXT: ldaw r1, sp[0] +; CHECK-NEXT: add r0, r1, r0 +; CHECK-NEXT: add r2, r0, r5 +; CHECK-NEXT: mov r3, r4 +; CHECK-NEXT: ldw r5, sp[3] +; CHECK-NEXT: ldw r4, sp[4] +; CHECK-NEXT: ldw r1, sp[1] +; CHECK-NEXT: ldw r0, sp[2] +; CHECK-NEXT: set sp, r2 +; CHECK-NEXT: bau r3 + call void (...)* @foo() + call void @llvm.eh.return.i32(i32 %offset, i8* %handler) + unreachable +} + +@offset = external constant i32 +@handler = external constant i8 +define i8* @EH2(i32 %r0, i32 %r1, i32 %r2, i32 %r3) { +entry: +; CHECK-LABEL: EH2 +; CHECK: entsp 3 +; CHECK: bl foo +; CHECK-NEXT: ldw r0, dp[offset] +; CHECK-NEXT: ldc r1, 12 +; CHECK-NEXT: ldaw r2, sp[0] +; CHECK-NEXT: add r1, r2, r1 +; CHECK-NEXT: add r2, r1, r0 +; CHECK-NEXT: ldaw r3, dp[handler] +; CHECK-NEXT: ldw r1, sp[1] +; CHECK-NEXT: ldw r0, sp[2] +; CHECK-NEXT: set sp, r2 +; CHECK-NEXT: bau r3 + call void (...)* @foo() + %0 = load i32* @offset + call void @llvm.eh.return.i32(i32 %0, i8* @handler) + unreachable +} + + +; FP: spill FP+SR+R0:1+R4:9 = entsp 2+2+6 +; But we dont actually spill or restore R0:1 +; CHECKFP-LABEL: Unwind0: +; CHECKFP: entsp 10 +; CHECKFP: stw r10, sp[1] +; CHECKFP: ldaw r10, sp[0] +; CHECKFP: stw r4, r10[9] +; CHECKFP: stw r5, r10[8] +; CHECKFP: stw r6, r10[7] +; CHECKFP: stw r7, r10[6] +; CHECKFP: stw r8, r10[5] +; CHECKFP: stw r9, r10[4] +; CHECKFP: ldw r9, r10[4] +; CHECKFP: ldw r8, r10[5] +; CHECKFP: ldw r7, r10[6] +; CHECKFP: ldw r6, r10[7] +; CHECKFP: ldw r5, r10[8] +; CHECKFP: ldw r4, r10[9] +; CHECKFP: set sp, r10 +; CHECKFP: ldw r10, sp[1] +; CHECKFP: retsp 10 +; +; !FP: spill R0:1+R4:10 = entsp 2+7 +; But we dont actually spill or restore R0:1 +; CHECK-LABEL: Unwind0: +; CHECK: entsp 9 +; CHECK: stw r4, sp[8] +; CHECK: stw r5, sp[7] +; CHECK: stw r6, sp[6] +; CHECK: stw r7, sp[5] +; CHECK: stw r8, sp[4] +; CHECK: stw r9, sp[3] +; CHECK: stw r10, sp[2] +; CHECK: ldw r10, sp[2] +; CHECK: ldw r9, sp[3] +; CHECK: ldw r8, sp[4] +; CHECK: ldw r7, sp[5] +; CHECK: ldw r6, sp[6] +; CHECK: ldw r5, sp[7] +; CHECK: ldw r4, sp[8] +; CHECK: retsp 9 +define void @Unwind0() { + call void @llvm.eh.unwind.init() + ret void +} + + +; FP: spill FP+SR+R0:1+R4:9+LR = entsp 2+2+6 + extsp 1 +; But we dont actually spill or restore R0:1 +; CHECKFP-LABEL: Unwind1: +; CHECKFP: entsp 10 +; CHECKFP: stw r10, sp[1] +; CHECKFP: ldaw r10, sp[0] +; CHECKFP: stw r4, r10[9] +; CHECKFP: stw r5, r10[8] +; CHECKFP: stw r6, r10[7] +; CHECKFP: stw r7, r10[6] +; CHECKFP: stw r8, r10[5] +; CHECKFP: stw r9, r10[4] +; CHECKFP: extsp 1 +; CHECKFP: bl foo +; CHECKFP: ldaw sp, sp[1] +; CHECKFP: ldw r9, r10[4] +; CHECKFP: ldw r8, r10[5] +; CHECKFP: ldw r7, r10[6] +; CHECKFP: ldw r6, r10[7] +; CHECKFP: ldw r5, r10[8] +; CHECKFP: ldw r4, r10[9] +; CHECKFP: set sp, r10 +; CHECKFP: ldw r10, sp[1] +; CHECKFP: retsp 10 +; +; !FP: spill R0:1+R4:10+LR = entsp 2+7+1 +; But we dont actually spill or restore R0:1 +; CHECK-LABEL: Unwind1: +; CHECK: entsp 10 +; CHECK: stw r4, sp[9] +; CHECK: stw r5, sp[8] +; CHECK: stw r6, sp[7] +; CHECK: stw r7, sp[6] +; CHECK: stw r8, sp[5] +; CHECK: stw r9, sp[4] +; CHECK: stw r10, sp[3] +; CHECK: bl foo +; CHECK: ldw r10, sp[3] +; CHECK: ldw r9, sp[4] +; CHECK: ldw r8, sp[5] +; CHECK: ldw r7, sp[6] +; CHECK: ldw r6, sp[7] +; CHECK: ldw r5, sp[8] +; CHECK: ldw r4, sp[9] +; CHECK: retsp 10 +define void @Unwind1() { + call void (...)* @foo() + call void @llvm.eh.unwind.init() + ret void +} + +; FP: spill FP+SR+R0:1+R4:9 = entsp 2+2+6 +; We dont spill R0:1 +; We only restore R0:1 during eh.return +; CHECKFP-LABEL: UnwindEH: +; CHECKFP: entsp 10 +; CHECKFP: .cfi_def_cfa_offset 40 +; CHECKFP: .cfi_offset 15, 0 +; CHECKFP: stw r10, sp[1] +; CHECKFP: .cfi_offset 10, -36 +; CHECKFP: ldaw r10, sp[0] +; CHECKFP: .cfi_def_cfa_register 10 +; CHECKFP: .cfi_offset 1, -32 +; CHECKFP: .cfi_offset 0, -28 +; CHECKFP: stw r4, r10[9] +; CHECKFP: .cfi_offset 4, -4 +; CHECKFP: stw r5, r10[8] +; CHECKFP: .cfi_offset 5, -8 +; CHECKFP: stw r6, r10[7] +; CHECKFP: .cfi_offset 6, -12 +; CHECKFP: stw r7, r10[6] +; CHECKFP: .cfi_offset 7, -16 +; CHECKFP: stw r8, r10[5] +; CHECKFP: .cfi_offset 8, -20 +; CHECKFP: stw r9, r10[4] +; CHECKFP: .cfi_offset 9, -24 +; CHECKFP: bt r0, .LBB{{[0-9_]+}} +; CHECKFP: ldw r9, r10[4] +; CHECKFP-NEXT: ldw r8, r10[5] +; CHECKFP-NEXT: ldw r7, r10[6] +; CHECKFP-NEXT: ldw r6, r10[7] +; CHECKFP-NEXT: ldw r5, r10[8] +; CHECKFP-NEXT: ldw r4, r10[9] +; CHECKFP-NEXT: set sp, r10 +; CHECKFP-NEXT: ldw r10, sp[1] +; CHECKFP-NEXT: retsp 10 +; CHECKFP: .LBB{{[0-9_]+}} +; CHECKFP-NEXT: ldc r2, 40 +; CHECKFP-NEXT: add r2, r10, r2 +; CHECKFP-NEXT: add r2, r2, r0 +; CHECKFP-NEXT: mov r3, r1 +; CHECKFP-NEXT: ldw r9, r10[4] +; CHECKFP-NEXT: ldw r8, r10[5] +; CHECKFP-NEXT: ldw r7, r10[6] +; CHECKFP-NEXT: ldw r6, r10[7] +; CHECKFP-NEXT: ldw r5, r10[8] +; CHECKFP-NEXT: ldw r4, r10[9] +; CHECKFP-NEXT: ldw r1, sp[2] +; CHECKFP-NEXT: ldw r0, sp[3] +; CHECKFP-NEXT: set sp, r2 +; CHECKFP-NEXT: bau r3 +; +; !FP: spill R0:1+R4:10 = entsp 2+7 +; We dont spill R0:1 +; We only restore R0:1 during eh.return +; CHECK-LABEL: UnwindEH: +; CHECK: entsp 9 +; CHECK: .cfi_def_cfa_offset 36 +; CHECK: .cfi_offset 15, 0 +; CHECK: .cfi_offset 1, -36 +; CHECK: .cfi_offset 0, -32 +; CHECK: stw r4, sp[8] +; CHECK: .cfi_offset 4, -4 +; CHECK: stw r5, sp[7] +; CHECK: .cfi_offset 5, -8 +; CHECK: stw r6, sp[6] +; CHECK: .cfi_offset 6, -12 +; CHECK: stw r7, sp[5] +; CHECK: .cfi_offset 7, -16 +; CHECK: stw r8, sp[4] +; CHECK: .cfi_offset 8, -20 +; CHECK: stw r9, sp[3] +; CHECK: .cfi_offset 9, -24 +; CHECK: stw r10, sp[2] +; CHECK: .cfi_offset 10, -28 +; CHECK: bt r0, .LBB{{[0-9_]+}} +; CHECK: ldw r10, sp[2] +; CHECK-NEXT: ldw r9, sp[3] +; CHECK-NEXT: ldw r8, sp[4] +; CHECK-NEXT: ldw r7, sp[5] +; CHECK-NEXT: ldw r6, sp[6] +; CHECK-NEXT: ldw r5, sp[7] +; CHECK-NEXT: ldw r4, sp[8] +; CHECK-NEXT: retsp 9 +; CHECK: .LBB{{[0-9_]+}} +; CHECK-NEXT: ldc r2, 36 +; CHECK-NEXT: ldaw r3, sp[0] +; CHECK-NEXT: add r2, r3, r2 +; CHECK-NEXT: add r2, r2, r0 +; CHECK-NEXT: mov r3, r1 +; CHECK-NEXT: ldw r10, sp[2] +; CHECK-NEXT: ldw r9, sp[3] +; CHECK-NEXT: ldw r8, sp[4] +; CHECK-NEXT: ldw r7, sp[5] +; CHECK-NEXT: ldw r6, sp[6] +; CHECK-NEXT: ldw r5, sp[7] +; CHECK-NEXT: ldw r4, sp[8] +; CHECK-NEXT: ldw r1, sp[0] +; CHECK-NEXT: ldw r0, sp[1] +; CHECK-NEXT: set sp, r2 +; CHECK-NEXT: bau r3 +define void @UnwindEH(i32 %offset, i8* %handler) { + call void @llvm.eh.unwind.init() + %cmp = icmp eq i32 %offset, 0 + br i1 %cmp, label %normal, label %eh +eh: + call void @llvm.eh.return.i32(i32 %offset, i8* %handler) + unreachable +normal: + ret void +} diff --git a/test/CodeGen/XCore/load.ll b/test/CodeGen/XCore/load.ll index 0622f1cd135e..c7fc2a33db1a 100644 --- a/test/CodeGen/XCore/load.ll +++ b/test/CodeGen/XCore/load.ll @@ -40,7 +40,7 @@ entry: ret i32 %2 } -@GConst = external constant i32 +@GConst = internal constant i32 42 define i32 @load_cp() nounwind { entry: ; CHECK-LABEL: load_cp: diff --git a/test/CodeGen/XCore/memcpy.ll b/test/CodeGen/XCore/memcpy.ll new file mode 100644 index 000000000000..fe424c50cb28 --- /dev/null +++ b/test/CodeGen/XCore/memcpy.ll @@ -0,0 +1,32 @@ +; RUN: llc < %s -march=xcore | FileCheck %s + +; Optimize memcpy to __memcpy_4 if src, dst and size are all 4 byte aligned. +define void @f1(i8* %dst, i8* %src, i32 %n) nounwind { +; CHECK-LABEL: f1: +; CHECK: bl __memcpy_4 +entry: + %0 = shl i32 %n, 2 + call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dst, i8* %src, i32 %0, i32 4, i1 false) + ret void +} + +; Can't optimize - size is not a multiple of 4. +define void @f2(i8* %dst, i8* %src, i32 %n) nounwind { +; CHECK-LABEL: f2: +; CHECK: bl memcpy +entry: + call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dst, i8* %src, i32 %n, i32 4, i1 false) + ret void +} + +; Can't optimize - alignment is not a multiple of 4. +define void @f3(i8* %dst, i8* %src, i32 %n) nounwind { +; CHECK-LABEL: f3: +; CHECK: bl memcpy +entry: + %0 = shl i32 %n, 2 + call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dst, i8* %src, i32 %0, i32 2, i1 false) + ret void +} + +declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i32, i1) nounwind diff --git a/test/CodeGen/XCore/resources.ll b/test/CodeGen/XCore/resources.ll index 5385010e138b..87bf3c204dc2 100644 --- a/test/CodeGen/XCore/resources.ll +++ b/test/CodeGen/XCore/resources.ll @@ -15,12 +15,14 @@ declare void @llvm.xcore.setd.p1i8(i8 addrspace(1)* %r, i32 %value) declare void @llvm.xcore.setc.p1i8(i8 addrspace(1)* %r, i32 %value) declare i32 @llvm.xcore.inshr.p1i8(i8 addrspace(1)* %r, i32 %value) declare i32 @llvm.xcore.outshr.p1i8(i8 addrspace(1)* %r, i32 %value) +declare void @llvm.xcore.clrpt.p1i8(i8 addrspace(1)* %r) declare void @llvm.xcore.setpt.p1i8(i8 addrspace(1)* %r, i32 %value) declare i32 @llvm.xcore.getts.p1i8(i8 addrspace(1)* %r) declare void @llvm.xcore.syncr.p1i8(i8 addrspace(1)* %r) declare void @llvm.xcore.settw.p1i8(i8 addrspace(1)* %r, i32 %value) declare void @llvm.xcore.setv.p1i8(i8 addrspace(1)* %r, i8* %p) declare void @llvm.xcore.setev.p1i8(i8 addrspace(1)* %r, i8* %p) +declare void @llvm.xcore.edu.p1i8(i8 addrspace(1)* %r) declare void @llvm.xcore.eeu.p1i8(i8 addrspace(1)* %r) declare void @llvm.xcore.setclk.p1i8.p1i8(i8 addrspace(1)* %a, i8 addrspace(1)* %b) declare void @llvm.xcore.setrdy.p1i8.p1i8(i8 addrspace(1)* %a, i8 addrspace(1)* %b) @@ -140,6 +142,13 @@ define i32 @outshr(i32 %value, i8 addrspace(1)* %r) { ret i32 %result } +define void @clrpt(i8 addrspace(1)* %r) { +; CHECK-LABEL: clrpt: +; CHECK: clrpt res[r0] + call void @llvm.xcore.clrpt.p1i8(i8 addrspace(1)* %r) + ret void +} + define void @setpt(i8 addrspace(1)* %r, i32 %value) { ; CHECK-LABEL: setpt: ; CHECK: setpt res[r0], r1 @@ -184,6 +193,13 @@ define void @setev(i8 addrspace(1)* %r, i8* %p) { ret void } +define void @edu(i8 addrspace(1)* %r) { +; CHECK-LABEL: edu: +; CHECK: edu res[r0] + call void @llvm.xcore.edu.p1i8(i8 addrspace(1)* %r) + ret void +} + define void @eeu(i8 addrspace(1)* %r) { ; CHECK-LABEL: eeu: ; CHECK: eeu res[r0] diff --git a/test/CodeGen/XCore/resources_combine.ll b/test/CodeGen/XCore/resources_combine.ll new file mode 100644 index 000000000000..20c184a53b99 --- /dev/null +++ b/test/CodeGen/XCore/resources_combine.ll @@ -0,0 +1,93 @@ +; RUN: llc -march=xcore < %s | FileCheck %s + +declare i32 @llvm.xcore.int.p1i8(i8 addrspace(1)* %r) +declare i32 @llvm.xcore.inct.p1i8(i8 addrspace(1)* %r) +declare i32 @llvm.xcore.testct.p1i8(i8 addrspace(1)* %r) +declare i32 @llvm.xcore.testwct.p1i8(i8 addrspace(1)* %r) +declare i32 @llvm.xcore.getts.p1i8(i8 addrspace(1)* %r) +declare void @llvm.xcore.outt.p1i8(i8 addrspace(1)* %r, i32 %value) +declare void @llvm.xcore.outct.p1i8(i8 addrspace(1)* %r, i32 %value) +declare void @llvm.xcore.chkct.p1i8(i8 addrspace(1)* %r, i32 %value) +declare void @llvm.xcore.setpt.p1i8(i8 addrspace(1)* %r, i32 %value) + +define i32 @int(i8 addrspace(1)* %r) nounwind { +; CHECK-LABEL: int: +; CHECK: int r0, res[r0] +; CHECK-NEXT: retsp 0 + %result = call i32 @llvm.xcore.int.p1i8(i8 addrspace(1)* %r) + %trunc = and i32 %result, 255 + ret i32 %trunc +} + +define i32 @inct(i8 addrspace(1)* %r) nounwind { +; CHECK-LABEL: inct: +; CHECK: inct r0, res[r0] +; CHECK-NEXT: retsp 0 + %result = call i32 @llvm.xcore.inct.p1i8(i8 addrspace(1)* %r) + %trunc = and i32 %result, 255 + ret i32 %trunc +} + +define i32 @testct(i8 addrspace(1)* %r) nounwind { +; CHECK-LABEL: testct: +; CHECK: testct r0, res[r0] +; CHECK-NEXT: retsp 0 + %result = call i32 @llvm.xcore.testct.p1i8(i8 addrspace(1)* %r) + %trunc = and i32 %result, 1 + ret i32 %trunc +} + +define i32 @testwct(i8 addrspace(1)* %r) nounwind { +; CHECK-LABEL: testwct: +; CHECK: testwct r0, res[r0] +; CHECK-NEXT: retsp 0 + %result = call i32 @llvm.xcore.testwct.p1i8(i8 addrspace(1)* %r) + %trunc = and i32 %result, 7 + ret i32 %trunc +} + +define i32 @getts(i8 addrspace(1)* %r) nounwind { +; CHECK-LABEL: getts: +; CHECK: getts r0, res[r0] +; CHECK-NEXT: retsp 0 + %result = call i32 @llvm.xcore.getts.p1i8(i8 addrspace(1)* %r) + %trunc = and i32 %result, 65535 + ret i32 %result +} + +define void @outt(i8 addrspace(1)* %r, i32 %value) nounwind { +; CHECK-LABEL: outt: +; CHECK-NOT: zext +; CHECK: outt res[r0], r1 +; CHECK-NEXT: retsp 0 + %trunc = and i32 %value, 255 + call void @llvm.xcore.outt.p1i8(i8 addrspace(1)* %r, i32 %trunc) + ret void +} + +define void @outct(i8 addrspace(1)* %r, i32 %value) nounwind { +; CHECK-LABEL: outct: +; CHECK-NOT: zext +; CHECK: outct res[r0], r1 + %trunc = and i32 %value, 255 + call void @llvm.xcore.outct.p1i8(i8 addrspace(1)* %r, i32 %trunc) + ret void +} + +define void @chkct(i8 addrspace(1)* %r, i32 %value) nounwind { +; CHECK-LABEL: chkct: +; CHECK-NOT: zext +; CHECK: chkct res[r0], r1 + %trunc = and i32 %value, 255 + call void @llvm.xcore.chkct.p1i8(i8 addrspace(1)* %r, i32 %trunc) + ret void +} + +define void @setpt(i8 addrspace(1)* %r, i32 %value) nounwind { +; CHECK-LABEL: setpt: +; CHECK-NOT: zext +; CHECK: setpt res[r0], r1 + %trunc = and i32 %value, 65535 + call void @llvm.xcore.setpt.p1i8(i8 addrspace(1)* %r, i32 %trunc) + ret void +} diff --git a/test/CodeGen/XCore/scavenging.ll b/test/CodeGen/XCore/scavenging.ll index 5b612d0f9b59..a0c8a2e09379 100644 --- a/test/CodeGen/XCore/scavenging.ll +++ b/test/CodeGen/XCore/scavenging.ll @@ -1,4 +1,5 @@ -; RUN: llc < %s -march=xcore +; RUN: llc < %s -march=xcore | FileCheck %s + @size = global i32 0 ; <i32*> [#uses=1] @g0 = external global i32 ; <i32*> [#uses=2] @g1 = external global i32 ; <i32*> [#uses=2] @@ -48,5 +49,69 @@ entry: call void @g(i32* %x1, i32* %1) nounwind ret void } - declare void @g(i32*, i32*) + + +; CHECK: .section .cp.rodata.cst4,"aMc",@progbits,4 +; CHECK: .align 4 +; CHECK: [[ARG5:.LCPI[0-9_]+]]: +; CHECK: .long 100003 +; CHECK: [[INDEX0:.LCPI[0-9_]+]]: +; CHECK: .long 80002 +; CHECK: [[INDEX1:.LCPI[0-9_]+]]: +; CHECK: .long 81002 +; CHECK: [[INDEX2:.LCPI[0-9_]+]]: +; CHECK: .long 82002 +; CHECK: [[INDEX3:.LCPI[0-9_]+]]: +; CHECK: .long 83002 +; CHECK: [[INDEX4:.LCPI[0-9_]+]]: +; CHECK: .long 84002 +; CHECK: .text +; !FP + large frame: spill SR+SR = entsp 2 + 100000 +; CHECK-LABEL: ScavengeSlots: +; CHECK: entsp 65535 +; CHECK: extsp 34467 +; scavenge r11 +; CHECK: ldaw r11, sp[0] +; scavenge r4 using SR spill slot +; CHECK: stw r4, sp[1] +; CHECK: ldw r4, cp{{\[}}[[ARG5]]{{\]}} +; r11 used to load 5th argument +; CHECK: ldw r11, r11[r4] +; CHECK: ldaw r4, sp[0] +; scavenge r5 using SR spill slot +; CHECK: stw r5, sp[0] +; CHECK: ldw r5, cp{{\[}}[[INDEX0]]{{\]}} +; r4 & r5 used by InsertSPConstInst() to emit STW_l3r instruction. +; CHECK: stw r0, r4[r5] +; CHECK: ldaw r0, sp[0] +; CHECK: ldw r5, cp{{\[}}[[INDEX1]]{{\]}} +; CHECK: stw r1, r0[r5] +; CHECK: ldaw r0, sp[0] +; CHECK: ldw r1, cp{{\[}}[[INDEX2]]{{\]}} +; CHECK: stw r2, r0[r1] +; CHECK: ldaw r0, sp[0] +; CHECK: ldw r1, cp{{\[}}[[INDEX3]]{{\]}} +; CHECK: stw r3, r0[r1] +; CHECK: ldaw r0, sp[0] +; CHECK: ldw r1, cp{{\[}}[[INDEX4]]{{\]}} +; CHECK: stw r11, r0[r1] +; CHECK: ldaw sp, sp[65535] +; CHECK: ldw r4, sp[1] +; CHECK: ldw r5, sp[0] +; CHECK: retsp 34467 +define void @ScavengeSlots(i32 %r0, i32 %r1, i32 %r2, i32 %r3, i32 %r4) nounwind { +entry: + %Data = alloca [100000 x i32] + %i0 = getelementptr inbounds [100000 x i32]* %Data, i32 0, i32 80000 + store volatile i32 %r0, i32* %i0 + %i1 = getelementptr inbounds [100000 x i32]* %Data, i32 0, i32 81000 + store volatile i32 %r1, i32* %i1 + %i2 = getelementptr inbounds [100000 x i32]* %Data, i32 0, i32 82000 + store volatile i32 %r2, i32* %i2 + %i3 = getelementptr inbounds [100000 x i32]* %Data, i32 0, i32 83000 + store volatile i32 %r3, i32* %i3 + %i4 = getelementptr inbounds [100000 x i32]* %Data, i32 0, i32 84000 + store volatile i32 %r4, i32* %i4 + ret void +} |
