summaryrefslogtreecommitdiff
path: root/test/CodeGen/SPARC
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2013-12-22 00:04:03 +0000
committerDimitry Andric <dim@FreeBSD.org>2013-12-22 00:04:03 +0000
commitf8af5cf600354830d4ccf59732403f0f073eccb9 (patch)
tree2ba0398b4c42ad4f55561327538044fd2c925a8b /test/CodeGen/SPARC
parent59d6cff90eecf31cb3dd860c4e786674cfdd42eb (diff)
Notes
Diffstat (limited to 'test/CodeGen/SPARC')
-rwxr-xr-xtest/CodeGen/SPARC/2011-01-11-CC.ll110
-rw-r--r--test/CodeGen/SPARC/2011-01-11-Call.ll40
-rw-r--r--test/CodeGen/SPARC/2011-01-11-FrameAddr.ll43
-rw-r--r--test/CodeGen/SPARC/2011-01-19-DelaySlot.ll105
-rw-r--r--test/CodeGen/SPARC/2011-01-21-ByValArgs.ll2
-rw-r--r--test/CodeGen/SPARC/2011-01-22-SRet.ll10
-rw-r--r--test/CodeGen/SPARC/2013-05-17-CallFrame.ll26
-rw-r--r--test/CodeGen/SPARC/64abi.ll37
-rw-r--r--test/CodeGen/SPARC/64bit.ll135
-rw-r--r--test/CodeGen/SPARC/64cond.ll89
-rw-r--r--test/CodeGen/SPARC/basictest.ll24
-rw-r--r--test/CodeGen/SPARC/blockaddr.ll77
-rw-r--r--test/CodeGen/SPARC/constpool.ll15
-rw-r--r--test/CodeGen/SPARC/exception.ll112
-rw-r--r--test/CodeGen/SPARC/float.ll249
-rw-r--r--test/CodeGen/SPARC/fp128.ll234
-rw-r--r--test/CodeGen/SPARC/globals.ll19
-rw-r--r--test/CodeGen/SPARC/leafproc.ll80
-rw-r--r--test/CodeGen/SPARC/lit.local.cfg2
-rw-r--r--test/CodeGen/SPARC/rem.ll39
-rw-r--r--test/CodeGen/SPARC/setjmp.ll72
-rw-r--r--test/CodeGen/SPARC/tls.ll73
-rw-r--r--test/CodeGen/SPARC/varargs.ll1
23 files changed, 1526 insertions, 68 deletions
diff --git a/test/CodeGen/SPARC/2011-01-11-CC.ll b/test/CodeGen/SPARC/2011-01-11-CC.ll
index f676fd836947b..50f3a65ff9a9b 100755
--- a/test/CodeGen/SPARC/2011-01-11-CC.ll
+++ b/test/CodeGen/SPARC/2011-01-11-CC.ll
@@ -1,5 +1,6 @@
; RUN: llc -march=sparc <%s | FileCheck %s -check-prefix=V8
; RUN: llc -march=sparc -mattr=v9 <%s | FileCheck %s -check-prefix=V9
+; RUN: llc -mtriple=sparc64-unknown-linux <%s | FileCheck %s -check-prefix=SPARC64
define i32 @test_addx(i64 %a, i64 %b, i64 %c) nounwind readnone noinline {
@@ -21,10 +22,10 @@ entry:
define i32 @test_select_int_icc(i32 %a, i32 %b, i32 %c) nounwind readnone noinline {
entry:
; V8: test_select_int_icc
-; V8: subcc
+; V8: cmp
; V8: {{be|bne}}
; V9: test_select_int_icc
-; V9: subcc
+; V9: cmp
; V9-NOT: {{be|bne}}
; V9: mov{{e|ne}} %icc
%0 = icmp eq i32 %a, 0
@@ -36,10 +37,10 @@ entry:
define float @test_select_fp_icc(i32 %a, float %f1, float %f2) nounwind readnone noinline {
entry:
; V8: test_select_fp_icc
-; V8: subcc
+; V8: cmp
; V8: {{be|bne}}
; V9: test_select_fp_icc
-; V9: subcc
+; V9: cmp
; V9-NOT: {{be|bne}}
; V9: fmovs{{e|ne}} %icc
%0 = icmp eq i32 %a, 0
@@ -50,10 +51,10 @@ entry:
define double @test_select_dfp_icc(i32 %a, double %f1, double %f2) nounwind readnone noinline {
entry:
; V8: test_select_dfp_icc
-; V8: subcc
+; V8: cmp
; V8: {{be|bne}}
; V9: test_select_dfp_icc
-; V9: subcc
+; V9: cmp
; V9-NOT: {{be|bne}}
; V9: fmovd{{e|ne}} %icc
%0 = icmp eq i32 %a, 0
@@ -63,11 +64,13 @@ entry:
define i32 @test_select_int_fcc(float %f, i32 %a, i32 %b) nounwind readnone noinline {
entry:
-;V8: test_select_int_fcc
+;V8-LABEL: test_select_int_fcc:
;V8: fcmps
+;V8-NEXT: nop
;V8: {{fbe|fbne}}
-;V9: test_select_int_fcc
+;V9-LABEL: test_select_int_fcc:
;V9: fcmps
+;V9-NEXT-NOT: nop
;V9-NOT: {{fbe|fbne}}
;V9: mov{{e|ne}} %fcc0
%0 = fcmp une float %f, 0.000000e+00
@@ -78,10 +81,10 @@ entry:
define float @test_select_fp_fcc(float %f, float %f1, float %f2) nounwind readnone noinline {
entry:
-;V8: test_select_fp_fcc
+;V8-LABEL: test_select_fp_fcc:
;V8: fcmps
;V8: {{fbe|fbne}}
-;V9: test_select_fp_fcc
+;V9-LABEL: test_select_fp_fcc:
;V9: fcmps
;V9-NOT: {{fbe|fbne}}
;V9: fmovs{{e|ne}} %fcc0
@@ -92,14 +95,97 @@ entry:
define double @test_select_dfp_fcc(double %f, double %f1, double %f2) nounwind readnone noinline {
entry:
-;V8: test_select_dfp_fcc
+;V8-LABEL: test_select_dfp_fcc:
;V8: fcmpd
+;V8-NEXT: nop
;V8: {{fbne|fbe}}
-;V9: test_select_dfp_fcc
+;V9-LABEL: test_select_dfp_fcc:
;V9: fcmpd
+;V9-NEXT-NOT: nop
;V9-NOT: {{fbne|fbe}}
;V9: fmovd{{e|ne}} %fcc0
%0 = fcmp une double %f, 0.000000e+00
%1 = select i1 %0, double %f1, double %f2
ret double %1
}
+
+define i32 @test_float_cc(double %a, double %b, i32 %c, i32 %d) {
+entry:
+; V8-LABEL: test_float_cc
+; V8: fcmpd
+; V8: {{fbl|fbuge}} .LBB
+; V8: fcmpd
+; V8: {{fbule|fbg}} .LBB
+
+; V9-LABEL: test_float_cc
+; V9: fcmpd
+; V9: {{fbl|fbuge}} .LBB
+; V9: fcmpd
+; V9: {{fbule|fbg}} .LBB
+
+ %0 = fcmp uge double %a, 0.000000e+00
+ br i1 %0, label %loop, label %loop.2
+
+loop:
+ %1 = icmp eq i32 %c, 10
+ br i1 %1, label %loop, label %exit.0
+
+loop.2:
+ %2 = fcmp ogt double %b, 0.000000e+00
+ br i1 %2, label %exit.1, label %loop
+
+exit.0:
+ ret i32 0
+
+exit.1:
+ ret i32 1
+}
+
+; V8-LABEL: test_adde_sube
+; V8: addcc
+; V8: addxcc
+; V8: addxcc
+; V8: addxcc
+; V8: subcc
+; V8: subxcc
+; V8: subxcc
+; V8: subxcc
+
+
+; V9-LABEL: test_adde_sube
+; V9: addcc
+; V9: addxcc
+; V9: addxcc
+; V9: addxcc
+; V9: subcc
+; V9: subxcc
+; V9: subxcc
+; V9: subxcc
+
+; SPARC64-LABEL: test_adde_sube
+; SPARC64: addcc
+; SPARC64: addxcc
+; SPARC64: addxcc
+; SPARC64: addxcc
+; SPARC64: subcc
+; SPARC64: subxcc
+; SPARC64: subxcc
+; SPARC64: subxcc
+
+
+define void @test_adde_sube(i8* %a, i8* %b, i8* %sum, i8* %diff) {
+entry:
+ %0 = bitcast i8* %a to i128*
+ %1 = bitcast i8* %b to i128*
+ %2 = load i128* %0
+ %3 = load i128* %1
+ %4 = add i128 %2, %3
+ %5 = bitcast i8* %sum to i128*
+ store i128 %4, i128* %5
+ tail call void asm sideeffect "", "=*m,*m"(i128 *%0, i128* %5) nounwind
+ %6 = load i128* %0
+ %7 = sub i128 %2, %6
+ %8 = bitcast i8* %diff to i128*
+ store i128 %7, i128* %8
+ ret void
+}
diff --git a/test/CodeGen/SPARC/2011-01-11-Call.ll b/test/CodeGen/SPARC/2011-01-11-Call.ll
index 7350e92324289..a0f478e119a3e 100644
--- a/test/CodeGen/SPARC/2011-01-11-Call.ll
+++ b/test/CodeGen/SPARC/2011-01-11-Call.ll
@@ -1,4 +1,24 @@
; RUN: llc -march=sparc -O0 <%s
+; RUN: llc -march=sparc <%s | FileCheck %s --check-prefix=V8
+; RUN: llc -march=sparcv9 <%s | FileCheck %s --check-prefix=V9
+
+; V8-LABEL: test
+; V8: save %sp
+; V8: call foo
+; V8-NEXT: nop
+; V8: call bar
+; V8-NEXT: nop
+; V8: jmp %i7+8
+; V8-NEXT: restore
+
+; V9-LABEL: test
+; V9: save %sp
+; V9: call foo
+; V9-NEXT: nop
+; V9: call bar
+; V9-NEXT: nop
+; V9: jmp %i7+8
+; V9-NEXT: restore
define void @test() nounwind {
entry:
@@ -11,3 +31,23 @@ declare i32 @foo(...)
declare void @bar(...)
+
+; V8-LABEL: test_tail_call_with_return
+; V8: save %sp
+; V8: call foo
+; V8-NEXT: nop
+; V8: jmp %i7+8
+; V8-NEXT: restore %g0, %o0, %o0
+
+; V9-LABEL: test_tail_call_with_return
+; V9: save %sp
+; V9: call foo
+; V9-NEXT: nop
+; V9: jmp %i7+8
+; V9-NEXT: restore %g0, %o0, %o0
+
+define i32 @test_tail_call_with_return() nounwind {
+entry:
+ %0 = tail call i32 (...)* @foo() nounwind
+ ret i32 %0
+}
diff --git a/test/CodeGen/SPARC/2011-01-11-FrameAddr.ll b/test/CodeGen/SPARC/2011-01-11-FrameAddr.ll
index 9e6583ca2ce14..7cc7868e44f93 100644
--- a/test/CodeGen/SPARC/2011-01-11-FrameAddr.ll
+++ b/test/CodeGen/SPARC/2011-01-11-FrameAddr.ll
@@ -3,26 +3,31 @@
;RUN: llc -march=sparc -regalloc=basic < %s | FileCheck %s -check-prefix=V8
;RUN: llc -march=sparc -regalloc=basic -mattr=v9 < %s | FileCheck %s -check-prefix=V9
+
define i8* @frameaddr() nounwind readnone {
entry:
-;V8: frameaddr
-;V8: or %g0, %fp, {{.+}}
+;V8-LABEL: frameaddr:
+;V8: save %sp, -96, %sp
+;V8: jmp %i7+8
+;V8: restore %g0, %fp, %o0
-;V9: frameaddr
-;V9: or %g0, %fp, {{.+}}
+;V9-LABEL: frameaddr:
+;V9: save %sp, -96, %sp
+;V9: jmp %i7+8
+;V9: restore %g0, %fp, %o0
%0 = tail call i8* @llvm.frameaddress(i32 0)
ret i8* %0
}
define i8* @frameaddr2() nounwind readnone {
entry:
-;V8: frameaddr2
+;V8-LABEL: frameaddr2:
;V8: ta 3
;V8: ld [%fp+56], {{.+}}
;V8: ld [{{.+}}+56], {{.+}}
;V8: ld [{{.+}}+56], {{.+}}
-;V9: frameaddr2
+;V9-LABEL: frameaddr2:
;V9: flushw
;V9: ld [%fp+56], {{.+}}
;V9: ld [{{.+}}+56], {{.+}}
@@ -37,28 +42,42 @@ declare i8* @llvm.frameaddress(i32) nounwind readnone
define i8* @retaddr() nounwind readnone {
entry:
-;V8: retaddr
-;V8: or %g0, %i7, {{.+}}
+;V8-LABEL: retaddr:
+;V8: or %g0, %o7, {{.+}}
+
+;V9-LABEL: retaddr:
+;V9: or %g0, %o7, {{.+}}
-;V9: retaddr
-;V9: or %g0, %i7, {{.+}}
%0 = tail call i8* @llvm.returnaddress(i32 0)
ret i8* %0
}
define i8* @retaddr2() nounwind readnone {
entry:
-;V8: retaddr2
+;V8-LABEL: retaddr2:
;V8: ta 3
;V8: ld [%fp+56], {{.+}}
;V8: ld [{{.+}}+56], {{.+}}
;V8: ld [{{.+}}+60], {{.+}}
-;V9: retaddr2
+;V9-LABEL: retaddr2:
;V9: flushw
;V9: ld [%fp+56], {{.+}}
;V9: ld [{{.+}}+56], {{.+}}
;V9: ld [{{.+}}+60], {{.+}}
+
+;V8LEAF-LABEL: retaddr2:
+;V8LEAF: ta 3
+;V8LEAF: ld [%fp+56], %[[R:[goli][0-7]]]
+;V8LEAF: ld [%[[R]]+56], %[[R1:[goli][0-7]]]
+;V8LEAF: ld [%[[R1]]+60], {{.+}}
+
+;V9LEAF-LABEL: retaddr2:
+;V9LEAF: flushw
+;V9LEAF: ld [%fp+56], %[[R:[goli][0-7]]]
+;V9LEAF: ld [%[[R]]+56], %[[R1:[goli][0-7]]]
+;V9LEAF: ld [%[[R1]]+60], {{.+}}
+
%0 = tail call i8* @llvm.returnaddress(i32 3)
ret i8* %0
}
diff --git a/test/CodeGen/SPARC/2011-01-19-DelaySlot.ll b/test/CodeGen/SPARC/2011-01-19-DelaySlot.ll
index 71fdb4e0d60f4..c71e7c00b9165 100644
--- a/test/CodeGen/SPARC/2011-01-19-DelaySlot.ll
+++ b/test/CodeGen/SPARC/2011-01-19-DelaySlot.ll
@@ -40,7 +40,7 @@ bb: ; preds = %entry, %bb
%a_addr.0 = add i32 %.pn, %a_addr.18
%3 = add nsw i32 %1, 1
%exitcond = icmp eq i32 %3, %b
-;CHECK: subcc
+;CHECK: cmp
;CHECK: bne
;CHECK-NOT: nop
br i1 %exitcond, label %bb5, label %bb
@@ -48,18 +48,18 @@ bb: ; preds = %entry, %bb
bb5: ; preds = %bb, %entry
%a_addr.1.lcssa = phi i32 [ %a, %entry ], [ %a_addr.0, %bb ]
;CHECK: jmp
-;CHECK-NEXT: restore
+;CHECK-NOT: restore
ret i32 %a_addr.1.lcssa
}
define i32 @test_inlineasm(i32 %a) nounwind {
entry:
-;CHECK: test_inlineasm
+;CHECK-LABEL: test_inlineasm:
;CHECK: sethi
;CHECK: !NO_APP
-;CHECK-NEXT: subcc
+;CHECK-NEXT: cmp
;CHECK-NEXT: bg
-;CHECK-NEXT: nop
+;CHECK-NEXT: or
tail call void asm sideeffect "sethi 0, %g0", ""() nounwind
%0 = icmp slt i32 %a, 0
br i1 %0, label %bb, label %bb1
@@ -80,11 +80,104 @@ declare i32 @bar(i32)
define i32 @test_implicit_def() nounwind {
entry:
-;UNOPT: test_implicit_def
+;UNOPT-LABEL: test_implicit_def:
;UNOPT: call func
;UNOPT-NEXT: nop
%0 = tail call i32 @func(i32* undef) nounwind
ret i32 0
}
+define i32 @prevent_o7_in_call_delay_slot(i32 %i0) {
+entry:
+;CHECK-LABEL: prevent_o7_in_call_delay_slot:
+;CHECK: add %i0, 2, %o5
+;CHECK: add %i0, 3, %o7
+;CHECK: add %o5, %o7, %o0
+;CHECK: call bar
+;CHECK-NEXT: nop
+ %0 = add nsw i32 %i0, 2
+ %1 = add nsw i32 %i0, 3
+ tail call void asm sideeffect "", "r,r,~{l0},~{l1},~{l2},~{l3},~{l4},~{l5},~{l6},~{l7},~{i0},~{i1},~{i2},~{i3},~{i4},~{i5},~{i6},~{i7},~{o0},~{o1},~{o2},~{o3},~{o4},~{o6},~{g1},~{g2},~{g3},~{g4},~{g5},~{g6},~{g7}"(i32 %0, i32 %1)
+ %2 = add nsw i32 %0, %1
+ %3 = tail call i32 @bar(i32 %2)
+ ret i32 %3
+}
+
+
declare i32 @func(i32*)
+
+
+define i32 @restore_add(i32 %a, i32 %b) {
+entry:
+;CHECK-LABEL: restore_add:
+;CHECK: jmp %i7+8
+;CHECK: restore %o0, %i1, %o0
+ %0 = tail call i32 @bar(i32 %a) nounwind
+ %1 = add nsw i32 %0, %b
+ ret i32 %1
+}
+
+define i32 @restore_add_imm(i32 %a) {
+entry:
+;CHECK-LABEL: restore_add_imm:
+;CHECK: jmp %i7+8
+;CHECK: restore %o0, 20, %o0
+ %0 = tail call i32 @bar(i32 %a) nounwind
+ %1 = add nsw i32 %0, 20
+ ret i32 %1
+}
+
+define i32 @restore_or(i32 %a) {
+entry:
+;CHECK-LABEL: restore_or:
+;CHECK: jmp %i7+8
+;CHECK: restore %g0, %o0, %o0
+ %0 = tail call i32 @bar(i32 %a) nounwind
+ ret i32 %0
+}
+
+define i32 @restore_or_imm(i32 %a) {
+entry:
+;CHECK-LABEL: restore_or_imm:
+;CHECK: or %o0, 20, %i0
+;CHECK: jmp %i7+8
+;CHECK: restore %g0, %g0, %g0
+ %0 = tail call i32 @bar(i32 %a) nounwind
+ %1 = or i32 %0, 20
+ ret i32 %1
+}
+
+
+define i32 @restore_sethi(i32 %a) {
+entry:
+;CHECK-LABEL: restore_sethi:
+;CHECK-NOT: sethi 3
+;CHECK: restore %g0, 3072, %o0
+ %0 = tail call i32 @bar(i32 %a) nounwind
+ %1 = icmp ne i32 %0, 0
+ %2 = select i1 %1, i32 3072, i32 0
+ ret i32 %2
+}
+
+define i32 @restore_sethi_3bit(i32 %a) {
+entry:
+;CHECK-LABEL: restore_sethi_3bit:
+;CHECK: sethi 6
+;CHECK-NOT: restore %g0, 6144, %o0
+ %0 = tail call i32 @bar(i32 %a) nounwind
+ %1 = icmp ne i32 %0, 0
+ %2 = select i1 %1, i32 6144, i32 0
+ ret i32 %2
+}
+
+define i32 @restore_sethi_large(i32 %a) {
+entry:
+;CHECK-LABEL: restore_sethi_large:
+;CHECK: sethi 4000, %i0
+;CHECK: restore %g0, %g0, %g0
+ %0 = tail call i32 @bar(i32 %a) nounwind
+ %1 = icmp ne i32 %0, 0
+ %2 = select i1 %1, i32 4096000, i32 0
+ ret i32 %2
+}
+
diff --git a/test/CodeGen/SPARC/2011-01-21-ByValArgs.ll b/test/CodeGen/SPARC/2011-01-21-ByValArgs.ll
index 85c16e4684edd..408b13d70a38f 100644
--- a/test/CodeGen/SPARC/2011-01-21-ByValArgs.ll
+++ b/test/CodeGen/SPARC/2011-01-21-ByValArgs.ll
@@ -6,7 +6,7 @@
define i32 @test() nounwind {
entry:
-;CHECK: test
+;CHECK-LABEL: test:
;CHECK: st
;CHECK: st
;CHECK: st
diff --git a/test/CodeGen/SPARC/2011-01-22-SRet.ll b/test/CodeGen/SPARC/2011-01-22-SRet.ll
index 5393392951e0c..fc44bc495f462 100644
--- a/test/CodeGen/SPARC/2011-01-22-SRet.ll
+++ b/test/CodeGen/SPARC/2011-01-22-SRet.ll
@@ -4,9 +4,9 @@
define weak void @make_foo(%struct.foo_t* noalias sret %agg.result, i32 %a, i32 %b, i32 %c) nounwind {
entry:
-;CHECK: make_foo
-;CHECK: ld [%fp+64], {{.+}}
-;CHECK: jmp %i7+12
+;CHECK-LABEL: make_foo:
+;CHECK: ld [%sp+64], {{.+}}
+;CHECK: jmp %o7+12
%0 = getelementptr inbounds %struct.foo_t* %agg.result, i32 0, i32 0
store i32 %a, i32* %0, align 4
%1 = getelementptr inbounds %struct.foo_t* %agg.result, i32 0, i32 1
@@ -18,9 +18,9 @@ entry:
define i32 @test() nounwind {
entry:
-;CHECK: test
+;CHECK-LABEL: test:
;CHECK: st {{.+}}, [%sp+64]
-;CHECK: make_foo
+;CHECK: call make_foo
;CHECK: unimp 12
%f = alloca %struct.foo_t, align 8
call void @make_foo(%struct.foo_t* noalias sret %f, i32 10, i32 20, i32 30) nounwind
diff --git a/test/CodeGen/SPARC/2013-05-17-CallFrame.ll b/test/CodeGen/SPARC/2013-05-17-CallFrame.ll
new file mode 100644
index 0000000000000..81f586fe8a7c0
--- /dev/null
+++ b/test/CodeGen/SPARC/2013-05-17-CallFrame.ll
@@ -0,0 +1,26 @@
+; RUN: llc -march=sparc < %s | FileCheck %s --check-prefix=V8
+; RUN: llc -march=sparcv9 < %s | FileCheck %s --check-prefix=SPARC64
+
+; V8-LABEL: variable_alloca_with_adj_call_stack
+; V8: save %sp, -96, %sp
+; V8: add {{.+}}, 96, %o0
+; V8: add %sp, -16, %sp
+; V8: call foo
+; V8: add %sp, 16, %sp
+
+; SPARC64-LABEL: variable_alloca_with_adj_call_stack
+; SPARC64: save %sp, -128, %sp
+; SPARC64: add {{.+}}, 2175, %o0
+; SPARC64: add %sp, -80, %sp
+; SPARC64: call foo
+; SPARC64: add %sp, 80, %sp
+
+define void @variable_alloca_with_adj_call_stack(i32 %num) {
+entry:
+ %0 = alloca i8, i32 %num, align 8
+ call void @foo(i8* %0, i8* %0, i8* %0, i8* %0, i8* %0, i8* %0, i8* %0, i8* %0, i8* %0, i8* %0)
+ ret void
+}
+
+
+declare void @foo(i8* , i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*);
diff --git a/test/CodeGen/SPARC/64abi.ll b/test/CodeGen/SPARC/64abi.ll
index ec97135721413..8b752a1a2c3c5 100644
--- a/test/CodeGen/SPARC/64abi.ll
+++ b/test/CodeGen/SPARC/64abi.ll
@@ -1,4 +1,4 @@
-; RUN: llc < %s -march=sparcv9 -disable-sparc-delay-filler | FileCheck %s
+; RUN: llc < %s -march=sparcv9 -disable-sparc-delay-filler -disable-sparc-leaf-proc | FileCheck %s
; CHECK: intarg
; The save/restore frame is not strictly necessary here, but we would need to
@@ -376,3 +376,38 @@ define signext i32 @ret_nosext(i32 signext %a0) {
define signext i32 @ret_nozext(i32 signext %a0) {
ret i32 %a0
}
+
+; CHECK-LABEL: test_register_directive
+; CHECK: .register %g2, #scratch
+; CHECK: .register %g3, #scratch
+; CHECK: add %i0, 2, %g2
+; CHECK: add %i0, 3, %g3
+define i32 @test_register_directive(i32 %i0) {
+entry:
+ %0 = add nsw i32 %i0, 2
+ %1 = add nsw i32 %i0, 3
+ tail call void asm sideeffect "", "r,r,~{l0},~{l1},~{l2},~{l3},~{l4},~{l5},~{l6},~{l7},~{i0},~{i1},~{i2},~{i3},~{i4},~{i5},~{i6},~{i7},~{o0},~{o1},~{o2},~{o3},~{o4},~{o5},~{o6},~{o7},~{g1},~{g4},~{g5},~{g6},~{g7}"(i32 %0, i32 %1)
+ %2 = add nsw i32 %0, %1
+ ret i32 %2
+}
+
+; CHECK-LABEL: test_large_stack
+
+; CHECK: sethi 16, %g1
+; CHECK: xor %g1, -176, %g1
+; CHECK: save %sp, %g1, %sp
+
+; CHECK: sethi 14, %g1
+; CHECK: xor %g1, -1, %g1
+; CHECK: add %g1, %fp, %g1
+; CHECK: call use_buf
+
+define i32 @test_large_stack() {
+entry:
+ %buffer1 = alloca [16384 x i8], align 8
+ %buffer1.sub = getelementptr inbounds [16384 x i8]* %buffer1, i32 0, i32 0
+ %0 = call i32 @use_buf(i32 16384, i8* %buffer1.sub)
+ ret i32 %0
+}
+
+declare i32 @use_buf(i32, i8*)
diff --git a/test/CodeGen/SPARC/64bit.ll b/test/CodeGen/SPARC/64bit.ll
index 2bbf7deb1684f..f5ed047592e95 100644
--- a/test/CodeGen/SPARC/64bit.ll
+++ b/test/CodeGen/SPARC/64bit.ll
@@ -1,13 +1,22 @@
-; RUN: llc < %s -march=sparcv9 | FileCheck %s
+; RUN: llc < %s -march=sparcv9 -disable-sparc-delay-filler -disable-sparc-leaf-proc | FileCheck %s
+; RUN: llc < %s -march=sparcv9 | FileCheck %s -check-prefix=OPT
-; CHECK: ret2:
+; CHECK-LABEL: ret2:
; CHECK: or %g0, %i1, %i0
+
+; OPT-LABEL: ret2:
+; OPT: jmp %o7+8
+; OPT: or %g0, %o1, %o0
define i64 @ret2(i64 %a, i64 %b) {
ret i64 %b
}
; CHECK: shl_imm
; CHECK: sllx %i0, 7, %i0
+
+; OPT-LABEL: shl_imm:
+; OPT: jmp %o7+8
+; OPT: sllx %o0, 7, %o0
define i64 @shl_imm(i64 %a) {
%x = shl i64 %a, 7
ret i64 %x
@@ -15,6 +24,10 @@ define i64 @shl_imm(i64 %a) {
; CHECK: sra_reg
; CHECK: srax %i0, %i1, %i0
+
+; OPT-LABEL: sra_reg:
+; OPT: jmp %o7+8
+; OPT: srax %o0, %o1, %o0
define i64 @sra_reg(i64 %a, i64 %b) {
%x = ashr i64 %a, %b
ret i64 %x
@@ -26,13 +39,21 @@ define i64 @sra_reg(i64 %a, i64 %b) {
; restore %g0, %g0, %o0
;
; CHECK: ret_imm0
-; CHECK: or %g0, %g0, %i0
+; CHECK: or %g0, 0, %i0
+
+; OPT: ret_imm0
+; OPT: jmp %o7+8
+; OPT: or %g0, 0, %o0
define i64 @ret_imm0() {
ret i64 0
}
; CHECK: ret_simm13
; CHECK: or %g0, -4096, %i0
+
+; OPT: ret_simm13
+; OPT: jmp %o7+8
+; OPT: or %g0, -4096, %o0
define i64 @ret_simm13() {
ret i64 -4096
}
@@ -41,13 +62,23 @@ define i64 @ret_simm13() {
; CHECK: sethi 4, %i0
; CHECK-NOT: or
; CHECK: restore
+
+; OPT: ret_sethi
+; OPT: jmp %o7+8
+; OPT: sethi 4, %o0
define i64 @ret_sethi() {
ret i64 4096
}
-; CHECK: ret_sethi
+; CHECK: ret_sethi_or
; CHECK: sethi 4, [[R:%[goli][0-7]]]
; CHECK: or [[R]], 1, %i0
+
+; OPT: ret_sethi_or
+; OPT: sethi 4, [[R:%[go][0-7]]]
+; OPT: jmp %o7+8
+; OPT: or [[R]], 1, %o0
+
define i64 @ret_sethi_or() {
ret i64 4097
}
@@ -55,6 +86,12 @@ define i64 @ret_sethi_or() {
; CHECK: ret_nimm33
; CHECK: sethi 4, [[R:%[goli][0-7]]]
; CHECK: xor [[R]], -4, %i0
+
+; OPT: ret_nimm33
+; OPT: sethi 4, [[R:%[go][0-7]]]
+; OPT: jmp %o7+8
+; OPT: xor [[R]], -4, %o0
+
define i64 @ret_nimm33() {
ret i64 -4100
}
@@ -124,6 +161,14 @@ define i64 @loads(i64* %p, i32* %q, i32* %r, i16* %s) {
ret i64 %x3
}
+; CHECK: load_bool
+; CHECK: ldub [%i0], %i0
+define i64 @load_bool(i1* %p) {
+ %a = load i1* %p
+ %b = zext i1 %a to i64
+ ret i64 %b
+}
+
; CHECK: stores
; CHECK: ldx [%i0+8], [[R:%[goli][0-7]]]
; CHECK: stx [[R]], [%i0+16]
@@ -181,3 +226,85 @@ define i64 @unsigned_divide(i64 %a, i64 %b) {
%r = udiv i64 %a, %b
ret i64 %r
}
+
+define void @access_fi() {
+entry:
+ %b = alloca [32 x i8], align 1
+ %arraydecay = getelementptr inbounds [32 x i8]* %b, i64 0, i64 0
+ call void @g(i8* %arraydecay) #2
+ ret void
+}
+
+declare void @g(i8*)
+
+; CHECK: expand_setcc
+; CHECK: cmp %i0, 1
+; CHECK: movl %xcc, 1,
+define i32 @expand_setcc(i64 %a) {
+ %cond = icmp sle i64 %a, 0
+ %cast2 = zext i1 %cond to i32
+ %RV = sub i32 1, %cast2
+ ret i32 %RV
+}
+
+; CHECK: spill_i64
+; CHECK: stx
+; CHECK: ldx
+define i64 @spill_i64(i64 %x) {
+ call void asm sideeffect "", "~{i0},~{i1},~{i2},~{i3},~{i4},~{i5},~{o0},~{o1},~{o2},~{o3},~{o4},~{o5},~{o7},~{l0},~{l1},~{l2},~{l3},~{l4},~{l5},~{l6},~{l7},~{g1},~{g2},~{g3},~{g4},~{g5},~{g6},~{g7}"()
+ ret i64 %x
+}
+
+; CHECK: bitcast_i64_f64
+; CHECK: std
+; CHECK: ldx
+define i64 @bitcast_i64_f64(double %x) {
+ %y = bitcast double %x to i64
+ ret i64 %y
+}
+
+; CHECK: bitcast_f64_i64
+; CHECK: stx
+; CHECK: ldd
+define double @bitcast_f64_i64(i64 %x) {
+ %y = bitcast i64 %x to double
+ ret double %y
+}
+
+; CHECK-LABEL: store_zero:
+; CHECK: stx %g0, [%i0]
+; CHECK: stx %g0, [%i1+8]
+
+; OPT-LABEL: store_zero:
+; OPT: stx %g0, [%o0]
+; OPT: stx %g0, [%o1+8]
+define i64 @store_zero(i64* nocapture %a, i64* nocapture %b) {
+entry:
+ store i64 0, i64* %a, align 8
+ %0 = getelementptr inbounds i64* %b, i32 1
+ store i64 0, i64* %0, align 8
+ ret i64 0
+}
+
+; CHECK-LABEL: bit_ops
+; CHECK: popc
+
+; OPT-LABEL: bit_ops
+; OPT: popc
+
+define i64 @bit_ops(i64 %arg) {
+entry:
+ %0 = tail call i64 @llvm.ctpop.i64(i64 %arg)
+ %1 = tail call i64 @llvm.ctlz.i64(i64 %arg, i1 true)
+ %2 = tail call i64 @llvm.cttz.i64(i64 %arg, i1 true)
+ %3 = tail call i64 @llvm.bswap.i64(i64 %arg)
+ %4 = add i64 %0, %1
+ %5 = add i64 %2, %3
+ %6 = add i64 %4, %5
+ ret i64 %6
+}
+
+declare i64 @llvm.ctpop.i64(i64) nounwind readnone
+declare i64 @llvm.ctlz.i64(i64, i1) nounwind readnone
+declare i64 @llvm.cttz.i64(i64, i1) nounwind readnone
+declare i64 @llvm.bswap.i64(i64) nounwind readnone
diff --git a/test/CodeGen/SPARC/64cond.ll b/test/CodeGen/SPARC/64cond.ll
index 6e66a262a4f2a..7451b04eadfe6 100644
--- a/test/CodeGen/SPARC/64cond.ll
+++ b/test/CodeGen/SPARC/64cond.ll
@@ -1,9 +1,9 @@
-; RUN: llc < %s -march=sparcv9 | FileCheck %s
-; Testing 64-bit conditionals.
+; RUN: llc < %s -mtriple=sparc64-pc-openbsd -disable-sparc-leaf-proc | FileCheck %s
+; Testing 64-bit conditionals. The sparc64 triple is an alias for sparcv9.
; CHECK: cmpri
-; CHECK: subcc %i1, 1
-; CHECK: bpe %xcc,
+; CHECK: cmp %i1, 1
+; CHECK: be %xcc,
define void @cmpri(i64* %p, i64 %x) {
entry:
%tobool = icmp eq i64 %x, 1
@@ -18,8 +18,8 @@ if.end:
}
; CHECK: cmprr
-; CHECK: subcc %i1, %i2
-; CHECK: bpgu %xcc,
+; CHECK: cmp %i1, %i2
+; CHECK: bgu %xcc,
define void @cmprr(i64* %p, i64 %x, i64 %y) {
entry:
%tobool = icmp ugt i64 %x, %y
@@ -34,9 +34,9 @@ if.end:
}
; CHECK: selecti32_xcc
-; CHECK: subcc %i0, %i1
+; CHECK: cmp %i0, %i1
; CHECK: movg %xcc, %i2, %i3
-; CHECK: or %g0, %i3, %i0
+; CHECK: restore %g0, %i3, %o0
define i32 @selecti32_xcc(i64 %x, i64 %y, i32 %a, i32 %b) {
entry:
%tobool = icmp sgt i64 %x, %y
@@ -45,12 +45,81 @@ entry:
}
; CHECK: selecti64_xcc
-; CHECK: subcc %i0, %i1
+; CHECK: cmp %i0, %i1
; CHECK: movg %xcc, %i2, %i3
-; CHECK: or %g0, %i3, %i0
+; CHECK: restore %g0, %i3, %o0
define i64 @selecti64_xcc(i64 %x, i64 %y, i64 %a, i64 %b) {
entry:
%tobool = icmp sgt i64 %x, %y
%rv = select i1 %tobool, i64 %a, i64 %b
ret i64 %rv
}
+
+; CHECK: selecti64_icc
+; CHECK: cmp %i0, %i1
+; CHECK: movg %icc, %i2, %i3
+; CHECK: restore %g0, %i3, %o0
+define i64 @selecti64_icc(i32 %x, i32 %y, i64 %a, i64 %b) {
+entry:
+ %tobool = icmp sgt i32 %x, %y
+ %rv = select i1 %tobool, i64 %a, i64 %b
+ ret i64 %rv
+}
+
+; CHECK: selecti64_fcc
+; CHECK: fcmps %f1, %f3
+; CHECK: movul %fcc0, %i2, %i3
+; CHECK: restore %g0, %i3, %o0
+define i64 @selecti64_fcc(float %x, float %y, i64 %a, i64 %b) {
+entry:
+ %tobool = fcmp ult float %x, %y
+ %rv = select i1 %tobool, i64 %a, i64 %b
+ ret i64 %rv
+}
+
+; CHECK: selectf32_xcc
+; CHECK: cmp %i0, %i1
+; CHECK: fmovsg %xcc, %f5, %f7
+; CHECK: fmovs %f7, %f1
+define float @selectf32_xcc(i64 %x, i64 %y, float %a, float %b) {
+entry:
+ %tobool = icmp sgt i64 %x, %y
+ %rv = select i1 %tobool, float %a, float %b
+ ret float %rv
+}
+
+; CHECK: selectf64_xcc
+; CHECK: cmp %i0, %i1
+; CHECK: fmovdg %xcc, %f4, %f6
+; CHECK: fmovd %f6, %f0
+define double @selectf64_xcc(i64 %x, i64 %y, double %a, double %b) {
+entry:
+ %tobool = icmp sgt i64 %x, %y
+ %rv = select i1 %tobool, double %a, double %b
+ ret double %rv
+}
+
+; The MOVXCC instruction can't use %g0 for its tied operand.
+; CHECK: select_consti64_xcc
+; CHECK: cmp
+; CHECK: movg %xcc, 123, %i{{[0-2]}}
+define i64 @select_consti64_xcc(i64 %x, i64 %y) {
+entry:
+ %tobool = icmp sgt i64 %x, %y
+ %rv = select i1 %tobool, i64 123, i64 0
+ ret i64 %rv
+}
+
+; CHECK-LABEL: setcc_resultty
+; CHECK: cmp
+; CHECK: movne %xcc, 1, [[R:%[gilo][0-7]]]
+; CHECK: or [[R]], %i1, %i0
+
+define i1 @setcc_resultty(i64 %a, i1 %b) {
+ %a0 = tail call { i64, i1 } @llvm.umul.with.overflow.i64(i64 %a, i64 32)
+ %a1 = extractvalue { i64, i1 } %a0, 1
+ %a4 = or i1 %a1, %b
+ ret i1 %a4
+}
+
+declare { i64, i1 } @llvm.umul.with.overflow.i64(i64, i64)
diff --git a/test/CodeGen/SPARC/basictest.ll b/test/CodeGen/SPARC/basictest.ll
index 4352e62463017..ba858253287a5 100644
--- a/test/CodeGen/SPARC/basictest.ll
+++ b/test/CodeGen/SPARC/basictest.ll
@@ -3,8 +3,8 @@
define i32 @test0(i32 %X) {
%tmp.1 = add i32 %X, 1
ret i32 %tmp.1
-; CHECK: test0:
-; CHECK: add %i0, 1, %i0
+; CHECK-LABEL: test0:
+; CHECK: add %o0, 1, %o0
}
@@ -13,14 +13,26 @@ define i32 @test1(i32 %X, i32 %Y) {
%A = xor i32 %X, %Y
%B = xor i32 %A, -1
ret i32 %B
-; CHECK: test1:
-; CHECK: xnor %i0, %i1, %i0
+; CHECK-LABEL: test1:
+; CHECK: xnor %o0, %o1, %o0
}
define i32 @test2(i32 %X, i32 %Y) {
%A = xor i32 %X, -1
%B = xor i32 %A, %Y
ret i32 %B
-; CHECK: test2:
-; CHECK: xnor %i0, %i1, %i0
+; CHECK-LABEL: test2:
+; CHECK: xnor %o0, %o1, %o0
}
+
+; CHECK-LABEL: store_zero:
+; CHECK: st %g0, [%o0]
+; CHECK: st %g0, [%o1+4]
+define i32 @store_zero(i32* %a, i32* %b) {
+entry:
+ store i32 0, i32* %a, align 4
+ %0 = getelementptr inbounds i32* %b, i32 1
+ store i32 0, i32* %0, align 4
+ ret i32 0
+}
+
diff --git a/test/CodeGen/SPARC/blockaddr.ll b/test/CodeGen/SPARC/blockaddr.ll
new file mode 100644
index 0000000000000..c3d527013c1bf
--- /dev/null
+++ b/test/CodeGen/SPARC/blockaddr.ll
@@ -0,0 +1,77 @@
+; RUN: llc < %s -march=sparc -relocation-model=static -code-model=small | FileCheck --check-prefix=abs32 %s
+; RUN: llc < %s -march=sparcv9 -relocation-model=static -code-model=small | FileCheck --check-prefix=abs32 %s
+; RUN: llc < %s -march=sparcv9 -relocation-model=static -code-model=medium | FileCheck --check-prefix=abs44 %s
+; RUN: llc < %s -march=sparcv9 -relocation-model=static -code-model=large | FileCheck --check-prefix=abs64 %s
+; RUN: llc < %s -march=sparc -relocation-model=pic -code-model=medium | FileCheck --check-prefix=v8pic32 %s
+; RUN: llc < %s -march=sparcv9 -relocation-model=pic -code-model=medium | FileCheck --check-prefix=v9pic32 %s
+
+;
+; copied from test/CodeGen/Mips/blockaddr.ll and modified for SPARC
+;
+@reg = common global i8* null, align 4
+
+define i8* @dummy(i8* %x) nounwind readnone noinline {
+entry:
+ ret i8* %x
+}
+
+; abs32-LABEL: func_block_addr:
+; abs32: sethi %hi([[BLK:.+]]), [[R:%[gilo][0-7]]]
+; abs32: call dummy
+; abs32: add [[R]], %lo([[BLK]]), %o0
+; abs32: jmp %o0
+
+; abs44-LABEL: func_block_addr:
+; abs44: sethi %h44([[BLK:.+]]), [[R:%[gilo][0-7]]]
+; abs44: add [[R]], %m44([[BLK]]), [[R1:%[gilo][0-7]]]
+; abs44: sllx [[R1]], 12, [[R2:%[gilo][0-7]]]
+; abs44: call dummy
+; abs44: add [[R2]], %l44([[BLK]]), %o0
+; abs44: jmp %o0
+
+; abs64-LABEL: func_block_addr:
+; abs64: sethi %hi([[BLK:.+]]), [[R:%[gilo][0-7]]]
+; abs64: add [[R]], %lo([[BLK]]), [[R1:%[gilo][0-7]]]
+; abs64: sethi %hh([[BLK]]), [[R2:%[gilo][0-7]]]
+; abs64: add [[R2]], %hm([[BLK]]), [[R3:%[gilo][0-7]]]
+; abs64: sllx [[R3]], 32, [[R4:%[gilo][0-7]]]
+; abs64: call dummy
+; abs64: add [[R2]], [[R1]], %o0
+; abs64: jmp %o0
+
+
+; v8pic32: func_block_addr
+; v8pic32: sethi %hi(_GLOBAL_OFFSET_TABLE_+{{.+}}), [[R:%[gilo][0-7]]]
+; v8pic32: or [[R]], %lo(_GLOBAL_OFFSET_TABLE_+{{.+}}), [[R1:%[gilo][0-7]]]
+; v8pic32: add [[R1]], %o7, %[[R2:[gilo][0-7]]]
+; v8pic32: sethi %hi([[BLK:.+]]), [[R3:%[gilo][0-7]]]
+; v8pic32: add [[R3]], %lo([[BLK]]), %[[R4:[gilo][0-7]]]
+; v8pic32: call dummy
+; v8pic32: ld [%[[R2]]+%[[R4]]], %o0
+; v8pic32: jmp %o0
+
+
+; v9pic32: func_block_addr
+; v9pic32: sethi %hi(_GLOBAL_OFFSET_TABLE_+{{.+}}), [[R:%[gilo][0-7]]]
+; v9pic32: or [[R]], %lo(_GLOBAL_OFFSET_TABLE_+{{.+}}), [[R1:%[gilo][0-7]]]
+; v9pic32: add [[R1]], %o7, %[[R2:[gilo][0-7]]]
+; v9pic32: sethi %hi([[BLK:.+]]), [[R3:%[gilo][0-7]]]
+; v9pic32: add [[R3]], %lo([[BLK]]), %[[R4:[gilo][0-7]]]
+; v9pic32: call dummy
+; v9pic32: ldx [%[[R2]]+%[[R4]]], %o0
+; v9pic32: jmp %o0
+
+
+define void @func_block_addr() nounwind {
+entry:
+ %call = tail call i8* @dummy(i8* blockaddress(@func_block_addr, %baz))
+ indirectbr i8* %call, [label %baz, label %foo]
+
+foo: ; preds = %foo, %entry
+ store i8* blockaddress(@func_block_addr, %foo), i8** @reg, align 4
+ br label %foo
+
+baz: ; preds = %entry
+ store i8* null, i8** @reg, align 4
+ ret void
+}
diff --git a/test/CodeGen/SPARC/constpool.ll b/test/CodeGen/SPARC/constpool.ll
index d93a53b3ac044..b861676ce3e1e 100644
--- a/test/CodeGen/SPARC/constpool.ll
+++ b/test/CodeGen/SPARC/constpool.ll
@@ -12,15 +12,17 @@ entry:
; abs32: floatCP
; abs32: sethi %hi(.LCPI0_0), %[[R:[gilo][0-7]]]
+; abs32: jmp %o7+8
; abs32: ld [%[[R]]+%lo(.LCPI0_0)], %f
-; abs32: jmp %i7+8
+
; abs44: floatCP
; abs44: sethi %h44(.LCPI0_0), %[[R1:[gilo][0-7]]]
; abs44: add %[[R1]], %m44(.LCPI0_0), %[[R2:[gilo][0-7]]]
; abs44: sllx %[[R2]], 12, %[[R3:[gilo][0-7]]]
+; abs44: jmp %o7+8
; abs44: ld [%[[R3]]+%l44(.LCPI0_0)], %f1
-; abs44: jmp %i7+8
+
; abs64: floatCP
; abs64: sethi %hi(.LCPI0_0), %[[R1:[gilo][0-7]]]
@@ -28,8 +30,9 @@ entry:
; abs64: sethi %hh(.LCPI0_0), %[[R3:[gilo][0-7]]]
; abs64: add %[[R3]], %hm(.LCPI0_0), %[[R4:[gilo][0-7]]]
; abs64: sllx %[[R4]], 32, %[[R5:[gilo][0-7]]]
+; abs64: jmp %o7+8
; abs64: ld [%[[R5]]+%[[R2]]], %f1
-; abs64: jmp %i7+8
+
; v8pic32: floatCP
; v8pic32: _GLOBAL_OFFSET_TABLE_
@@ -38,6 +41,9 @@ entry:
; v8pic32: ld [%[[GOT:[gilo][0-7]]]+%[[Goffs]]], %[[Gaddr:[gilo][0-7]]]
; v8pic32: ld [%[[Gaddr]]], %f0
; v8pic32: jmp %i7+8
+; v8pic32: restore
+
+
; v9pic32: floatCP
; v9pic32: _GLOBAL_OFFSET_TABLE_
@@ -46,3 +52,6 @@ entry:
; v9pic32: ldx [%[[GOT:[gilo][0-7]]]+%[[Goffs]]], %[[Gaddr:[gilo][0-7]]]
; v9pic32: ld [%[[Gaddr]]], %f1
; v9pic32: jmp %i7+8
+; v9pic32: restore
+
+
diff --git a/test/CodeGen/SPARC/exception.ll b/test/CodeGen/SPARC/exception.ll
new file mode 100644
index 0000000000000..cb5b6e5c11684
--- /dev/null
+++ b/test/CodeGen/SPARC/exception.ll
@@ -0,0 +1,112 @@
+; RUN: llc < %s -march=sparc | FileCheck %s
+
+
+%struct.__fundamental_type_info_pseudo = type { %struct.__type_info_pseudo }
+%struct.__type_info_pseudo = type { i8*, i8* }
+
+@_ZTIi = external constant %struct.__fundamental_type_info_pseudo
+@_ZTIf = external constant %struct.__fundamental_type_info_pseudo
+@.cst = linker_private unnamed_addr constant [12 x i8] c"catched int\00", align 64
+@.cst1 = linker_private unnamed_addr constant [14 x i8] c"catched float\00", align 64
+
+; CHECK-LABEL: main:
+; CHECK: .cfi_startproc
+; CHECK: .cfi_def_cfa_register 30
+; CHECK: .cfi_window_save
+; CHECK: .cfi_register 15, 31
+
+; CHECK: call __cxa_throw
+; CHECK: call __cxa_throw
+
+; CHECK: call __cxa_begin_catch
+; CHECK: call __cxa_end_catch
+
+; CHECK: call __cxa_begin_catch
+; CHECK: call __cxa_end_catch
+
+; CHECK: .cfi_endproc
+
+define i32 @main(i32 %argc, i8** nocapture readnone %argv) unnamed_addr #0 {
+entry:
+ %0 = icmp eq i32 %argc, 2
+ %1 = tail call i8* @__cxa_allocate_exception(i32 4) #1
+ br i1 %0, label %"3", label %"4"
+
+"3": ; preds = %entry
+ %2 = bitcast i8* %1 to i32*
+ store i32 0, i32* %2, align 4
+ invoke void @__cxa_throw(i8* %1, i8* bitcast (%struct.__fundamental_type_info_pseudo* @_ZTIi to i8*), void (i8*)* null) #2
+ to label %3 unwind label %"8"
+
+; <label>:3 ; preds = %"3"
+ unreachable
+
+"4": ; preds = %entry
+ %4 = bitcast i8* %1 to float*
+ store float 1.000000e+00, float* %4, align 4
+
+
+ invoke void @__cxa_throw(i8* %1, i8* bitcast (%struct.__fundamental_type_info_pseudo* @_ZTIf to i8*), void (i8*)* null) #2
+ to label %5 unwind label %"8"
+
+; <label>:5 ; preds = %"4"
+ unreachable
+
+"5": ; preds = %"13", %"11"
+ %6 = phi i32 [ 2, %"13" ], [ 0, %"11" ]
+ ret i32 %6
+
+"8": ; preds = %"4", %"3"
+ %exc = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @__gxx_personality_v0
+ catch %struct.__fundamental_type_info_pseudo* @_ZTIi
+ catch %struct.__fundamental_type_info_pseudo* @_ZTIf
+ %exc_ptr12 = extractvalue { i8*, i32 } %exc, 0
+ %filter13 = extractvalue { i8*, i32 } %exc, 1
+ %typeid = tail call i32 @llvm.eh.typeid.for(i8* bitcast (%struct.__fundamental_type_info_pseudo* @_ZTIi to i8*))
+ %7 = icmp eq i32 %filter13, %typeid
+ br i1 %7, label %"11", label %8
+
+; <label>:8 ; preds = %"8"
+ %typeid8 = tail call i32 @llvm.eh.typeid.for(i8* bitcast (%struct.__fundamental_type_info_pseudo* @_ZTIf to i8*))
+ %9 = icmp eq i32 %filter13, %typeid8
+ br i1 %9, label %"13", label %"9"
+
+"9": ; preds = %8
+ resume { i8*, i32 } %exc
+
+"11": ; preds = %"8"
+ %10 = tail call i8* @__cxa_begin_catch(i8* %exc_ptr12) #1
+ %11 = tail call i32 @puts(i8* getelementptr inbounds ([12 x i8]* @.cst, i32 0, i32 0))
+ tail call void @__cxa_end_catch() #1
+ br label %"5"
+
+"13": ; preds = %8
+ %12 = tail call i8* @__cxa_begin_catch(i8* %exc_ptr12) #1
+ %13 = tail call i32 @puts(i8* getelementptr inbounds ([14 x i8]* @.cst1, i32 0, i32 0))
+ tail call void @__cxa_end_catch() #1
+ br label %"5"
+}
+
+; Function Attrs: nounwind
+declare i8* @__cxa_allocate_exception(i32) #1
+
+; Function Attrs: noreturn
+declare void @__cxa_throw(i8*, i8*, void (i8*)*) #2
+
+declare void @__cxa_end_catch()
+
+; Function Attrs: nounwind readnone
+declare i32 @llvm.eh.typeid.for(i8*) #3
+
+; Function Attrs: nounwind
+declare i8* @__cxa_begin_catch(i8*) #1
+
+; Function Attrs: nounwind
+declare i32 @puts(i8* nocapture readonly) #1
+
+declare i32 @__gxx_personality_v0(i32, i64, i8*, i8*)
+
+attributes #0 = { "no-frame-pointer-elim-non-leaf"="false" }
+attributes #1 = { nounwind }
+attributes #2 = { noreturn }
+attributes #3 = { nounwind readnone }
diff --git a/test/CodeGen/SPARC/float.ll b/test/CodeGen/SPARC/float.ll
new file mode 100644
index 0000000000000..66367042cad9a
--- /dev/null
+++ b/test/CodeGen/SPARC/float.ll
@@ -0,0 +1,249 @@
+; RUN: llc -march=sparc < %s | FileCheck %s -check-prefix=V8
+; RUN: llc -march=sparc -O0 < %s | FileCheck %s -check-prefix=V8-UNOPT
+; RUN: llc -march=sparc -mattr=v9 < %s | FileCheck %s -check-prefix=V9
+; RUN: llc -mtriple=sparc64-unknown-linux < %s | FileCheck %s -check-prefix=SPARC64
+
+; V8-LABEL: test_neg:
+; V8: call get_double
+; V8: fnegs %f0, %f0
+
+; V8-UNOPT-LABEL: test_neg:
+; V8-UNOPT: fnegs
+; V8-UNOPT: ! implicit-def
+; V8-UNOPT: fmovs {{.+}}, %f0
+; V8-UNOPT: fmovs {{.+}}, %f1
+
+; V9-LABEL: test_neg:
+; V9: fnegd %f0, %f0
+
+; SPARC64-LABEL: test_neg:
+; SPARC64: fnegd %f0, %f0
+
+define double @test_neg() {
+entry:
+ %0 = tail call double @get_double()
+ %1 = fsub double -0.000000e+00, %0
+ ret double %1
+}
+
+; V8-LABEL: test_abs:
+; V8: fabss %f0, %f0
+
+; V8-UNOPT-LABEL: test_abs:
+; V8-UNOPT: fabss
+; V8-UNOPT: ! implicit-def
+; V8-UNOPT: fmovs {{.+}}, %f0
+; V8-UNOPT: fmovs {{.+}}, %f1
+
+; V9-LABEL: test_abs:
+; V9: fabsd %f0, %f0
+
+
+; SPARC64-LABEL: test_abs:
+; SPARC64: fabsd %f0, %f0
+
+define double @test_abs() {
+entry:
+ %0 = tail call double @get_double()
+ %1 = tail call double @llvm.fabs.f64(double %0)
+ ret double %1
+}
+
+declare double @get_double()
+declare double @llvm.fabs.f64(double) nounwind readonly
+
+; V8-LABEL: test_v9_floatreg:
+; V8: fsubd {{.+}}, {{.+}}, {{.+}}
+; V8: faddd {{.+}}, {{.+}}, [[R:%f(((1|2)?(0|2|4|6|8))|30)]]
+; V8: std [[R]], [%{{.+}}]
+; V8: ldd [%{{.+}}], %f0
+
+; V9-LABEL: test_v9_floatreg:
+; V9: fsubd {{.+}}, {{.+}}, {{.+}}
+; V9: faddd {{.+}}, {{.+}}, [[R:%f((3(2|4|6|8))|((4|5)(0|2|4|6|8))|(60|62))]]
+; V9: fmovd [[R]], %f0
+
+; SPARC64-LABEL: test_v9_floatreg:
+; SPARC64: fsubd {{.+}}, {{.+}}, {{.+}}
+; SPARC64: faddd {{.+}}, {{.+}}, [[R:%f((3(2|4|6|8))|((4|5)(0|2|4|6|8))|(60|62))]]
+; SPARC64: fmovd [[R]], %f0
+
+define double @test_v9_floatreg() {
+entry:
+ %0 = tail call double @get_double()
+ %1 = tail call double @get_double()
+ %2 = fsub double %0, %1
+ tail call void asm sideeffect "", "~{f0},~{f2},~{f3},~{f4},~{f5},~{f6},~{f7},~{f8},~{f9},~{f10},~{f11},~{f12},~{f13},~{f14},~{f15},~{f16},~{f17},~{f18},~{f19},~{f20},~{f21},~{f22},~{f23},~{f24},~{f25},~{f26},~{f27},~{f28},~{f29},~{f30},~{f31}"()
+ %3 = fadd double %2, %2
+ ret double %3
+}
+
+; V8-LABEL: test_xtos_stox
+; V8: call __floatdisf
+; V8: call __fixsfdi
+
+; V9-LABEL: test_xtos_stox
+; V9: call __floatdisf
+; V9: call __fixsfdi
+
+; SPARC64-LABEL: test_xtos_stox
+; SPARC64: fxtos
+; SPARC64: fstox
+
+define void @test_xtos_stox(i64 %a, i64* %ptr0, float* %ptr1) {
+entry:
+ %0 = sitofp i64 %a to float
+ store float %0, float* %ptr1, align 8
+ %1 = fptosi float %0 to i64
+ store i64 %1, i64* %ptr0, align 8
+ ret void
+}
+
+; V8-LABEL: test_itos_stoi
+; V8: fitos
+; V8: fstoi
+
+; V9-LABEL: test_itos_stoi
+; V9: fitos
+; V9: fstoi
+
+; SPARC64-LABEL: test_itos_stoi
+; SPARC64: fitos
+; SPARC64: fstoi
+
+define void @test_itos_stoi(i32 %a, i32* %ptr0, float* %ptr1) {
+entry:
+ %0 = sitofp i32 %a to float
+ store float %0, float* %ptr1, align 8
+ %1 = fptosi float %0 to i32
+ store i32 %1, i32* %ptr0, align 8
+ ret void
+}
+
+
+; V8-LABEL: test_xtod_dtox
+; V8: call __floatdidf
+; V8: call __fixdfdi
+
+; V9-LABEL: test_xtod_dtox
+; V9: call __floatdidf
+; V9: call __fixdfdi
+
+; SPARC64-LABEL: test_xtod_dtox
+; SPARC64: fxtod
+; SPARC64: fdtox
+
+define void @test_xtod_dtox(i64 %a, i64* %ptr0, double* %ptr1) {
+entry:
+ %0 = sitofp i64 %a to double
+ store double %0, double* %ptr1, align 8
+ %1 = fptosi double %0 to i64
+ store i64 %1, i64* %ptr0, align 8
+ ret void
+}
+
+; V8-LABEL: test_itod_dtoi
+; V8: fitod
+; V8: fdtoi
+
+; V9-LABEL: test_itod_dtoi
+; V9: fitod
+; V9: fdtoi
+
+; SPARC64-LABEL: test_itod_dtoi
+; SPARC64: fitod
+; SPARC64: fdtoi
+
+define void @test_itod_dtoi(i32 %a, i32* %ptr0, double* %ptr1) {
+entry:
+ %0 = sitofp i32 %a to double
+ store double %0, double* %ptr1, align 8
+ %1 = fptosi double %0 to i32
+ store i32 %1, i32* %ptr0, align 8
+ ret void
+}
+
+; V8-LABEL: test_uxtos_stoux
+; V8: call __floatundisf
+; V8: call __fixunssfdi
+
+; V9-LABEL: test_uxtos_stoux
+; V9: call __floatundisf
+; V9: call __fixunssfdi
+
+; SPARC64-LABEL: test_uxtos_stoux
+; SPARC64-NOT: call __floatundisf
+; SPARC64-NOT: call __fixunssfdi
+
+define void @test_uxtos_stoux(i64 %a, i64* %ptr0, float* %ptr1) {
+entry:
+ %0 = uitofp i64 %a to float
+ store float %0, float* %ptr1, align 8
+ %1 = fptoui float %0 to i64
+ store i64 %1, i64* %ptr0, align 8
+ ret void
+}
+
+; V8-LABEL: test_utos_stou
+; V8: fdtos
+; V8: fstoi
+
+; V9-LABEL: test_utos_stou
+; V9: fdtos
+; V9: fstoi
+
+; SPARC64-LABEL: test_utos_stou
+; SPARC64: fdtos
+; SPARC64: fstoi
+
+define void @test_utos_stou(i32 %a, i32* %ptr0, float* %ptr1) {
+entry:
+ %0 = uitofp i32 %a to float
+ store float %0, float* %ptr1, align 8
+ %1 = fptoui float %0 to i32
+ store i32 %1, i32* %ptr0, align 8
+ ret void
+}
+
+
+; V8-LABEL: test_uxtod_dtoux
+; V8: call __floatundidf
+; V8: call __fixunsdfdi
+
+; V9-LABEL: test_uxtod_dtoux
+; V9: call __floatundidf
+; V9: call __fixunsdfdi
+
+; SPARC64-LABEL: test_uxtod_dtoux
+; SPARC64-NOT: call __floatundidf
+; SPARC64-NOT: call __floatunsdfdi
+
+define void @test_uxtod_dtoux(i64 %a, i64* %ptr0, double* %ptr1) {
+entry:
+ %0 = uitofp i64 %a to double
+ store double %0, double* %ptr1, align 8
+ %1 = fptoui double %0 to i64
+ store i64 %1, i64* %ptr0, align 8
+ ret void
+}
+
+; V8-LABEL: test_utod_dtou
+; V8-NOT: fitod
+; V8: fdtoi
+
+; V9-LABEL: test_utod_dtou
+; V9-NOT: fitod
+; V9: fdtoi
+
+; SPARC64-LABEL: test_utod_dtou
+; SPARC64-NOT: fitod
+; SPARC64: fdtoi
+
+define void @test_utod_dtou(i32 %a, double %b, i32* %ptr0, double* %ptr1) {
+entry:
+ %0 = uitofp i32 %a to double
+ store double %0, double* %ptr1, align 8
+ %1 = fptoui double %b to i32
+ store i32 %1, i32* %ptr0, align 8
+ ret void
+}
diff --git a/test/CodeGen/SPARC/fp128.ll b/test/CodeGen/SPARC/fp128.ll
new file mode 100644
index 0000000000000..c761361e773e3
--- /dev/null
+++ b/test/CodeGen/SPARC/fp128.ll
@@ -0,0 +1,234 @@
+; RUN: llc < %s -march=sparc -mattr=hard-quad-float | FileCheck %s --check-prefix=HARD
+; RUN: llc < %s -march=sparc -mattr=-hard-quad-float | FileCheck %s --check-prefix=SOFT
+
+
+; HARD-LABEL: f128_ops
+; HARD: ldd
+; HARD: ldd
+; HARD: ldd
+; HARD: ldd
+; HARD: faddq [[R0:.+]], [[R1:.+]], [[R2:.+]]
+; HARD: fsubq [[R2]], [[R3:.+]], [[R4:.+]]
+; HARD: fmulq [[R4]], [[R5:.+]], [[R6:.+]]
+; HARD: fdivq [[R6]], [[R2]]
+; HARD: std
+; HARD: std
+
+; SOFT-LABEL: f128_ops
+; SOFT: ldd
+; SOFT: ldd
+; SOFT: ldd
+; SOFT: ldd
+; SOFT: call _Q_add
+; SOFT: call _Q_sub
+; SOFT: call _Q_mul
+; SOFT: call _Q_div
+; SOFT: std
+; SOFT: std
+
+define void @f128_ops(fp128* noalias sret %scalar.result, fp128* byval %a, fp128* byval %b, fp128* byval %c, fp128* byval %d) {
+entry:
+ %0 = load fp128* %a, align 8
+ %1 = load fp128* %b, align 8
+ %2 = load fp128* %c, align 8
+ %3 = load fp128* %d, align 8
+ %4 = fadd fp128 %0, %1
+ %5 = fsub fp128 %4, %2
+ %6 = fmul fp128 %5, %3
+ %7 = fdiv fp128 %6, %4
+ store fp128 %7, fp128* %scalar.result, align 8
+ ret void
+}
+
+; HARD-LABEL: f128_spill
+; HARD: std %f{{.+}}, [%[[S0:.+]]]
+; HARD: std %f{{.+}}, [%[[S1:.+]]]
+; HARD-DAG: ldd [%[[S0]]], %f{{.+}}
+; HARD-DAG: ldd [%[[S1]]], %f{{.+}}
+; HARD: jmp
+
+; SOFT-LABEL: f128_spill
+; SOFT: std %f{{.+}}, [%[[S0:.+]]]
+; SOFT: std %f{{.+}}, [%[[S1:.+]]]
+; SOFT-DAG: ldd [%[[S0]]], %f{{.+}}
+; SOFT-DAG: ldd [%[[S1]]], %f{{.+}}
+; SOFT: jmp
+
+define void @f128_spill(fp128* noalias sret %scalar.result, fp128* byval %a) {
+entry:
+ %0 = load fp128* %a, align 8
+ call void asm sideeffect "", "~{f0},~{f1},~{f2},~{f3},~{f4},~{f5},~{f6},~{f7},~{f8},~{f9},~{f10},~{f11},~{f12},~{f13},~{f14},~{f15},~{f16},~{f17},~{f18},~{f19},~{f20},~{f21},~{f22},~{f23},~{f24},~{f25},~{f26},~{f27},~{f28},~{f29},~{f30},~{f31}"()
+ store fp128 %0, fp128* %scalar.result, align 8
+ ret void
+}
+
+; HARD-LABEL: f128_compare
+; HARD: fcmpq
+; HARD-NEXT: nop
+
+; SOFT-LABEL: f128_compare
+; SOFT: _Q_cmp
+
+define i32 @f128_compare(fp128* byval %f0, fp128* byval %f1, i32 %a, i32 %b) {
+entry:
+ %0 = load fp128* %f0, align 8
+ %1 = load fp128* %f1, align 8
+ %cond = fcmp ult fp128 %0, %1
+ %ret = select i1 %cond, i32 %a, i32 %b
+ ret i32 %ret
+}
+
+; HARD-LABEL: f128_compare2
+; HARD: fcmpq
+; HARD: fb{{ule|g}}
+
+; SOFT-LABEL: f128_compare2
+; SOFT: _Q_cmp
+; SOFT: cmp
+
+define i32 @f128_compare2() {
+entry:
+ %0 = fcmp ogt fp128 undef, 0xL00000000000000000000000000000000
+ br i1 %0, label %"5", label %"7"
+
+"5": ; preds = %entry
+ ret i32 0
+
+"7": ; preds = %entry
+ ret i32 1
+}
+
+
+; HARD-LABEL: f128_abs
+; HARD: fabss
+
+; SOFT-LABEL: f128_abs
+; SOFT: fabss
+
+define void @f128_abs(fp128* noalias sret %scalar.result, fp128* byval %a) {
+entry:
+ %0 = load fp128* %a, align 8
+ %1 = tail call fp128 @llvm.fabs.f128(fp128 %0)
+ store fp128 %1, fp128* %scalar.result, align 8
+ ret void
+}
+
+declare fp128 @llvm.fabs.f128(fp128) nounwind readonly
+
+; HARD-LABEL: int_to_f128
+; HARD: fitoq
+
+; SOFT-LABEL: int_to_f128
+; SOFT: _Q_itoq
+
+define void @int_to_f128(fp128* noalias sret %scalar.result, i32 %i) {
+entry:
+ %0 = sitofp i32 %i to fp128
+ store fp128 %0, fp128* %scalar.result, align 8
+ ret void
+}
+
+; HARD-LABEL: fp128_unaligned
+; HARD: ldub
+; HARD: faddq
+; HARD: stb
+; HARD: jmp
+
+; SOFT-LABEL: fp128_unaligned
+; SOFT: ldub
+; SOFT: call _Q_add
+; SOFT: stb
+; SOFT: jmp
+
+define void @fp128_unaligned(fp128* %a, fp128* %b, fp128* %c) {
+entry:
+ %0 = load fp128* %a, align 1
+ %1 = load fp128* %b, align 1
+ %2 = fadd fp128 %0, %1
+ store fp128 %2, fp128* %c, align 1
+ ret void
+}
+
+; HARD-LABEL: uint_to_f128
+; HARD: fdtoq
+
+; SOFT-LABEL: uint_to_f128
+; SOFT: _Q_utoq
+
+define void @uint_to_f128(fp128* noalias sret %scalar.result, i32 %i) {
+entry:
+ %0 = uitofp i32 %i to fp128
+ store fp128 %0, fp128* %scalar.result, align 8
+ ret void
+}
+
+; HARD-LABEL: f128_to_i32
+; HARD: fqtoi
+; HARD: fqtoi
+
+; SOFT-LABEL: f128_to_i32
+; SOFT: call _Q_qtou
+; SOFT: call _Q_qtoi
+
+
+define i32 @f128_to_i32(fp128* %a, fp128* %b) {
+entry:
+ %0 = load fp128* %a, align 8
+ %1 = load fp128* %b, align 8
+ %2 = fptoui fp128 %0 to i32
+ %3 = fptosi fp128 %1 to i32
+ %4 = add i32 %2, %3
+ ret i32 %4
+}
+
+; HARD-LABEL: test_itoq_qtoi
+; HARD: call _Q_lltoq
+; HARD: call _Q_qtoll
+; HARD: fitoq
+; HARD: fqtoi
+
+; SOFT-LABEL: test_itoq_qtoi
+; SOFT: call _Q_lltoq
+; SOFT: call _Q_qtoll
+; SOFT: call _Q_itoq
+; SOFT: call _Q_qtoi
+
+define void @test_itoq_qtoi(i64 %a, i32 %b, i64* %ptr0, fp128* %ptr1) {
+entry:
+ %0 = sitofp i64 %a to fp128
+ store fp128 %0, fp128* %ptr1, align 8
+ %1 = fptosi fp128 %0 to i64
+ store i64 %1, i64* %ptr0, align 8
+ %2 = sitofp i32 %b to fp128
+ store fp128 %2, fp128* %ptr1, align 8
+ %3 = fptosi fp128 %2 to i32
+ %4 = bitcast i64* %ptr0 to i32*
+ store i32 %3, i32* %4, align 8
+ ret void
+}
+
+; HARD-LABEL: test_utoq_qtou
+; HARD-DAG: call _Q_ulltoq
+; HARD-DAG: call _Q_qtoull
+; HARD-DAG: fdtoq
+; HARD-DAG: fqtoi
+
+; SOFT-LABEL: test_utoq_qtou
+; SOFT-DAG: call _Q_ulltoq
+; SOFT-DAG: call _Q_qtoull
+; SOFT-DAG: call _Q_utoq
+; SOFT-DAG: call _Q_qtou
+
+define void @test_utoq_qtou(i64 %a, i32 %b, i64* %ptr0, fp128* %ptr1) {
+entry:
+ %0 = uitofp i64 %a to fp128
+ store fp128 %0, fp128* %ptr1, align 8
+ %1 = fptoui fp128 %0 to i64
+ store i64 %1, i64* %ptr0, align 8
+ %2 = uitofp i32 %b to fp128
+ store fp128 %2, fp128* %ptr1, align 8
+ %3 = fptoui fp128 %2 to i32
+ %4 = bitcast i64* %ptr0 to i32*
+ store i32 %3, i32* %4, align 8
+ ret void
+}
diff --git a/test/CodeGen/SPARC/globals.ll b/test/CodeGen/SPARC/globals.ll
index 8d8de58f7ccf4..7e3effe3f4cef 100644
--- a/test/CodeGen/SPARC/globals.ll
+++ b/test/CodeGen/SPARC/globals.ll
@@ -14,15 +14,17 @@ define zeroext i8 @loadG() {
; abs32: loadG
; abs32: sethi %hi(G), %[[R:[gilo][0-7]]]
-; abs32: ldub [%[[R]]+%lo(G)], %i0
-; abs32: jmp %i7+8
+; abs32: jmp %o7+8
+; abs32: ldub [%[[R]]+%lo(G)], %o0
+
; abs44: loadG
; abs44: sethi %h44(G), %[[R1:[gilo][0-7]]]
; abs44: add %[[R1]], %m44(G), %[[R2:[gilo][0-7]]]
; abs44: sllx %[[R2]], 12, %[[R3:[gilo][0-7]]]
-; abs44: ldub [%[[R3]]+%l44(G)], %i0
-; abs44: jmp %i7+8
+; abs44: jmp %o7+8
+; abs44: ldub [%[[R3]]+%l44(G)], %o0
+
; abs64: loadG
; abs64: sethi %hi(G), %[[R1:[gilo][0-7]]]
@@ -30,8 +32,9 @@ define zeroext i8 @loadG() {
; abs64: sethi %hh(G), %[[R3:[gilo][0-7]]]
; abs64: add %[[R3]], %hm(G), %[[R4:[gilo][0-7]]]
; abs64: sllx %[[R4]], 32, %[[R5:[gilo][0-7]]]
-; abs64: ldub [%[[R5]]+%[[R2]]], %i0
-; abs64: jmp %i7+8
+; abs64: jmp %o7+8
+; abs64: ldub [%[[R5]]+%[[R2]]], %o0
+
; v8pic32: loadG
; v8pic32: _GLOBAL_OFFSET_TABLE_
@@ -40,6 +43,8 @@ define zeroext i8 @loadG() {
; v8pic32: ld [%[[GOT:[gilo][0-7]]]+%[[Goffs]]], %[[Gaddr:[gilo][0-7]]]
; v8pic32: ldub [%[[Gaddr]]], %i0
; v8pic32: jmp %i7+8
+; v8pic32: restore
+
; v9pic32: loadG
; v9pic32: _GLOBAL_OFFSET_TABLE_
@@ -48,3 +53,5 @@ define zeroext i8 @loadG() {
; v9pic32: ldx [%[[GOT:[gilo][0-7]]]+%[[Goffs]]], %[[Gaddr:[gilo][0-7]]]
; v9pic32: ldub [%[[Gaddr]]], %i0
; v9pic32: jmp %i7+8
+; v9pic32: restore
+
diff --git a/test/CodeGen/SPARC/leafproc.ll b/test/CodeGen/SPARC/leafproc.ll
new file mode 100644
index 0000000000000..0a7ae083d208b
--- /dev/null
+++ b/test/CodeGen/SPARC/leafproc.ll
@@ -0,0 +1,80 @@
+; RUN: llc -march=sparc -disable-sparc-leaf-proc=0 < %s | FileCheck %s
+
+; CHECK-LABEL: func_nobody:
+; CHECK: jmp %o7+8
+; CHECK-NEXT: nop
+define void @func_nobody() {
+entry:
+ ret void
+}
+
+
+; CHECK-LABEL: return_int_const:
+; CHECK: jmp %o7+8
+; CHECK-NEXT: or %g0, 1729, %o0
+define i32 @return_int_const() {
+entry:
+ ret i32 1729
+}
+
+; CHECK-LABEL: return_double_const:
+; CHECK: sethi
+; CHECK: jmp %o7+8
+; CHECK-NEXT: ldd {{.*}}, %f0
+
+define double @return_double_const() {
+entry:
+ ret double 0.000000e+00
+}
+
+; CHECK-LABEL: leaf_proc_with_args:
+; CHECK: add {{%o[0-1]}}, {{%o[0-1]}}, [[R:%[go][0-7]]]
+; CHECK: jmp %o7+8
+; CHECK-NEXT: add [[R]], %o2, %o0
+
+define i32 @leaf_proc_with_args(i32 %a, i32 %b, i32 %c) {
+entry:
+ %0 = add nsw i32 %b, %a
+ %1 = add nsw i32 %0, %c
+ ret i32 %1
+}
+
+; CHECK-LABEL: leaf_proc_with_args_in_stack:
+; CHECK-DAG: ld [%sp+92], {{%[go][0-7]}}
+; CHECK-DAG: ld [%sp+96], {{%[go][0-7]}}
+; CHECK: jmp %o7+8
+; CHECK-NEXT: add {{.*}}, %o0
+define i32 @leaf_proc_with_args_in_stack(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h) {
+entry:
+ %0 = add nsw i32 %b, %a
+ %1 = add nsw i32 %0, %c
+ %2 = add nsw i32 %1, %d
+ %3 = add nsw i32 %2, %e
+ %4 = add nsw i32 %3, %f
+ %5 = add nsw i32 %4, %g
+ %6 = add nsw i32 %5, %h
+ ret i32 %6
+}
+
+; CHECK-LABEL: leaf_proc_with_local_array:
+; CHECK: add %sp, -104, %sp
+; CHECK: or %g0, 1, [[R1:%[go][0-7]]]
+; CHECK: st [[R1]], [%sp+96]
+; CHECK: or %g0, 2, [[R2:%[go][0-7]]]
+; CHECK: st [[R2]], [%sp+100]
+; CHECK: ld {{.+}}, %o0
+; CHECK: jmp %o7+8
+; CHECK-NEXT: add %sp, 104, %sp
+
+define i32 @leaf_proc_with_local_array(i32 %a, i32 %b, i32 %c) {
+entry:
+ %array = alloca [2 x i32], align 4
+ %0 = sub nsw i32 %b, %c
+ %1 = getelementptr inbounds [2 x i32]* %array, i32 0, i32 0
+ store i32 1, i32* %1, align 4
+ %2 = getelementptr inbounds [2 x i32]* %array, i32 0, i32 1
+ store i32 2, i32* %2, align 4
+ %3 = getelementptr inbounds [2 x i32]* %array, i32 0, i32 %a
+ %4 = load i32* %3, align 4
+ ret i32 %4
+}
diff --git a/test/CodeGen/SPARC/lit.local.cfg b/test/CodeGen/SPARC/lit.local.cfg
index 6f30a87979673..4d344fa91a9ea 100644
--- a/test/CodeGen/SPARC/lit.local.cfg
+++ b/test/CodeGen/SPARC/lit.local.cfg
@@ -1,5 +1,3 @@
-config.suffixes = ['.ll', '.c', '.cpp', '.test']
-
targets = set(config.root.targets_to_build.split())
if not 'Sparc' in targets:
config.unsupported = True
diff --git a/test/CodeGen/SPARC/rem.ll b/test/CodeGen/SPARC/rem.ll
new file mode 100644
index 0000000000000..abef1fc112b47
--- /dev/null
+++ b/test/CodeGen/SPARC/rem.ll
@@ -0,0 +1,39 @@
+; RUN: llc < %s -march=sparcv9 | FileCheck %s
+
+; CHECK-LABEL: test1:
+; CHECK: sdivx %o0, %o1, %o2
+; CHECK-NEXT: mulx %o2, %o1, %o1
+; CHECK-NEXT: jmp %o7+8
+; CHECK-NEXT: sub %o0, %o1, %o0
+
+define i64 @test1(i64 %X, i64 %Y) {
+ %tmp1 = srem i64 %X, %Y
+ ret i64 %tmp1
+}
+
+; CHECK-LABEL: test2:
+; CHECK: udivx %o0, %o1, %o2
+; CHECK-NEXT: mulx %o2, %o1, %o1
+; CHECK-NEXT: jmp %o7+8
+; CHECK-NEXT: sub %o0, %o1, %o0
+
+define i64 @test2(i64 %X, i64 %Y) {
+ %tmp1 = urem i64 %X, %Y
+ ret i64 %tmp1
+}
+
+; PR18150
+; CHECK-LABEL: test3
+; CHECK: sethi 2545, [[R0:%[gilo][0-7]]]
+; CHECK: or [[R0]], 379, [[R1:%[gilo][0-7]]]
+; CHECK: mulx %o0, [[R1]], [[R2:%[gilo][0-7]]]
+; CHECK: udivx [[R2]], 1021, [[R3:%[gilo][0-7]]]
+; CHECK: mulx [[R3]], 1021, [[R4:%[gilo][0-7]]]
+; CHECK: sub [[R2]], [[R4]], %o0
+
+define i64 @test3(i64 %b) {
+entry:
+ %mul = mul i64 %b, 2606459
+ %rem = urem i64 %mul, 1021
+ ret i64 %rem
+}
diff --git a/test/CodeGen/SPARC/setjmp.ll b/test/CodeGen/SPARC/setjmp.ll
new file mode 100644
index 0000000000000..39984fb14bcb6
--- /dev/null
+++ b/test/CodeGen/SPARC/setjmp.ll
@@ -0,0 +1,72 @@
+;RUN: llc -march=sparc < %s | FileCheck %s
+;RUN: llc -march=sparcv9 < %s | FileCheck %s --check-prefix=V9
+
+
+%0 = type { [32 x i32] }
+%struct.jmpbuf_env = type { i32, i32, [1 x %struct.__jmp_buf_tag], i32 }
+%struct.__jmp_buf_tag = type { [3 x i32], i32, %0 }
+
+@jenv = common unnamed_addr global %struct.jmpbuf_env* null
+@.cst = linker_private unnamed_addr constant [30 x i8] c"in bar with jmp_buf's id: %d\0A\00", align 64
+
+; CHECK-LABEL: foo
+; CHECK-DAG: st {{.+}}, [%i0]
+; CHECK-DAG: st {{.+}}, [%i0+4]
+; CHECK: call _setjmp
+; CHECK: ld [%fp+{{.+}}], %[[R:[gilo][0-7]]]
+; CHECK: st %o0, [%[[R]]+{{.+}}]
+
+; V9-LABEL: foo
+; V9-DAG: st {{.+}}, [%i0]
+; V9-DAG: st {{.+}}, [%i0+4]
+; V9: call _setjmp
+; V9: ldx [%fp+{{.+}}], %[[R:[gilo][0-7]]]
+; V9: st %o0, [%[[R]]+{{.+}}]
+
+; Function Attrs: nounwind
+define i32 @foo(%struct.jmpbuf_env* byval %inbuf) #0 {
+entry:
+ %0 = getelementptr inbounds %struct.jmpbuf_env* %inbuf, i32 0, i32 0
+ store i32 0, i32* %0, align 4, !tbaa !4
+ %1 = getelementptr inbounds %struct.jmpbuf_env* %inbuf, i32 0, i32 1
+ store i32 1, i32* %1, align 4, !tbaa !4
+ %2 = getelementptr inbounds %struct.jmpbuf_env* %inbuf, i32 0, i32 2, i32 0
+ %3 = call i32 @_setjmp(%struct.__jmp_buf_tag* %2) #2
+ %4 = getelementptr inbounds %struct.jmpbuf_env* %inbuf, i32 0, i32 3
+ store i32 %3, i32* %4, align 4, !tbaa !4
+ store %struct.jmpbuf_env* %inbuf, %struct.jmpbuf_env** @jenv, align 4, !tbaa !3
+ %5 = load i32* %1, align 4, !tbaa !4
+ %6 = icmp eq i32 %5, 1
+ %7 = icmp eq i32 %3, 0
+ %or.cond = and i1 %6, %7
+ br i1 %or.cond, label %"4.i", label %bar.exit
+
+"4.i": ; preds = %entry
+ call void @longjmp(%struct.__jmp_buf_tag* %2, i32 0) #1
+ unreachable
+
+bar.exit: ; preds = %entry
+ %8 = load i32* %0, align 4, !tbaa !4
+ %9 = call i32 (i8*, ...)* @printf(i8* noalias getelementptr inbounds ([30 x i8]* @.cst, i32 0, i32 0), i32 %8) #0
+ ret i32 0
+}
+
+; Function Attrs: nounwind returns_twice
+declare i32 @_setjmp(%struct.__jmp_buf_tag*) #2
+
+; Function Attrs: noreturn nounwind
+declare void @longjmp(%struct.__jmp_buf_tag*, i32) #1
+
+; Function Attrs: nounwind
+declare i32 @printf(i8* nocapture, ...) #0
+
+
+attributes #0 = { nounwind }
+attributes #1 = { noreturn nounwind }
+attributes #2 = { nounwind returns_twice }
+
+!0 = metadata !{metadata !"alias set 6: struct.jmpbuf_env*", metadata !1}
+!1 = metadata !{metadata !1}
+!2 = metadata !{metadata !"alias set 3: int", metadata !1}
+!3 = metadata !{metadata !0, metadata !0, i64 0}
+!4 = metadata !{metadata !2, metadata !2, i64 0}
diff --git a/test/CodeGen/SPARC/tls.ll b/test/CodeGen/SPARC/tls.ll
new file mode 100644
index 0000000000000..660ddff0fae9b
--- /dev/null
+++ b/test/CodeGen/SPARC/tls.ll
@@ -0,0 +1,73 @@
+; RUN: llc <%s -march=sparc -relocation-model=static | FileCheck %s --check-prefix=v8abs
+; RUN: llc <%s -march=sparcv9 -relocation-model=static | FileCheck %s --check-prefix=v9abs
+; RUN: llc <%s -march=sparc -relocation-model=pic | FileCheck %s --check-prefix=pic
+; RUN: llc <%s -march=sparcv9 -relocation-model=pic | FileCheck %s --check-prefix=pic
+
+
+@local_symbol = internal thread_local global i32 0
+@extern_symbol = external thread_local global i32
+
+; v8abs-LABEL: test_tls_local
+; v8abs: sethi %tle_hix22(local_symbol), [[R0:%[goli][0-7]]]
+; v8abs: xor [[R0]], %tle_lox10(local_symbol), [[R1:%[goli][0-7]]]
+; v8abs: ld [%g7+[[R1]]]
+
+; v9abs-LABEL: test_tls_local
+; v9abs: sethi %tle_hix22(local_symbol), [[R0:%[goli][0-7]]]
+; v9abs: xor [[R0]], %tle_lox10(local_symbol), [[R1:%[goli][0-7]]]
+; v9abs: ld [%g7+[[R1]]]
+
+; pic-LABEL: test_tls_local
+; pic: or {{%[goli][0-7]}}, %lo(_GLOBAL_OFFSET_TABLE_+{{.+}}), [[PC:%[goli][0-7]]]
+; pic: add [[PC]], %o7, [[GOTBASE:%[goli][0-7]]]
+; pic-DAG: sethi %tldm_hi22(local_symbol), [[R0:%[goli][0-7]]]
+; pic-DAG: add [[R0]], %tldm_lo10(local_symbol), [[R1:%[goli][0-7]]]
+; pic-DAG: add [[GOTBASE]], [[R1]], %o0, %tldm_add(local_symbol)
+; pic-DAG: call __tls_get_addr, %tldm_call(local_symbol)
+; pic-DAG: sethi %tldo_hix22(local_symbol), [[R2:%[goli][0-7]]]
+; pic-DAG: xor [[R2]], %tldo_lox10(local_symbol), [[R3:%[goli][0-7]]]
+; pic: add %o0, [[R3]], {{.+}}, %tldo_add(local_symbol)
+
+define i32 @test_tls_local() {
+entry:
+ %0 = load i32* @local_symbol, align 4
+ %1 = add i32 %0, 1
+ store i32 %1, i32* @local_symbol, align 4
+ ret i32 %1
+}
+
+
+; v8abs-LABEL: test_tls_extern
+; v8abs: or {{%[goli][0-7]}}, %lo(_GLOBAL_OFFSET_TABLE_+{{.+}}), [[PC:%[goli][0-7]]]
+; v8abs: add [[PC]], %o7, %[[GOTBASE:[goli][0-7]]]
+; v8abs: sethi %tie_hi22(extern_symbol), [[R1:%[goli][0-7]]]
+; v8abs: add [[R1]], %tie_lo10(extern_symbol), %[[R2:[goli][0-7]]]
+; v8abs: ld [%[[GOTBASE]]+%[[R2]]], [[R3:%[goli][0-7]]], %tie_ld(extern_symbol)
+; v8abs: add %g7, [[R3]], %[[R4:[goli][0-7]]], %tie_add(extern_symbol)
+; v8abs: ld [%[[R4]]]
+
+; v9abs-LABEL: test_tls_extern
+; v9abs: or {{%[goli][0-7]}}, %lo(_GLOBAL_OFFSET_TABLE_+{{.+}}), [[PC:%[goli][0-7]]]
+; v9abs: add [[PC]], %o7, %[[GOTBASE:[goli][0-7]]]
+; v9abs: sethi %tie_hi22(extern_symbol), [[R1:%[goli][0-7]]]
+; v9abs: add [[R1]], %tie_lo10(extern_symbol), %[[R2:[goli][0-7]]]
+; v9abs: ldx [%[[GOTBASE]]+%[[R2]]], [[R3:%[goli][0-7]]], %tie_ldx(extern_symbol)
+; v9abs: add %g7, [[R3]], %[[R4:[goli][0-7]]], %tie_add(extern_symbol)
+; v9abs: ld [%[[R4]]]
+
+; pic-LABEL: test_tls_extern
+; pic: or {{%[goli][0-7]}}, %lo(_GLOBAL_OFFSET_TABLE_+{{.+}}), [[PC:%[goli][0-7]]]
+; pic: add [[PC]], %o7, [[GOTBASE:%[goli][0-7]]]
+; pic: sethi %tgd_hi22(extern_symbol), [[R0:%[goli][0-7]]]
+; pic: add [[R0]], %tgd_lo10(extern_symbol), [[R1:%[goli][0-7]]]
+; pic: add [[GOTBASE]], [[R1]], %o0, %tgd_add(extern_symbol)
+; pic: call __tls_get_addr, %tgd_call(extern_symbol)
+; pic-NEXT: nop
+
+define i32 @test_tls_extern() {
+entry:
+ %0 = load i32* @extern_symbol, align 4
+ %1 = add i32 %0, 1
+ store i32 %1, i32* @extern_symbol, align 4
+ ret i32 %1
+}
diff --git a/test/CodeGen/SPARC/varargs.ll b/test/CodeGen/SPARC/varargs.ll
index b13f90e6ca71d..76e16cd44f6a4 100644
--- a/test/CodeGen/SPARC/varargs.ll
+++ b/test/CodeGen/SPARC/varargs.ll
@@ -1,4 +1,5 @@
; RUN: llc < %s -disable-block-placement | FileCheck %s
+; RUN: llc < %s -disable-block-placement -disable-sparc-leaf-proc=0 | FileCheck %s
target datalayout = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-n32:64-S128"
target triple = "sparcv9-sun-solaris"