summaryrefslogtreecommitdiff
path: root/test/CodeGen/SPARC
diff options
context:
space:
mode:
Diffstat (limited to 'test/CodeGen/SPARC')
-rwxr-xr-xtest/CodeGen/SPARC/2011-01-11-CC.ll4
-rw-r--r--test/CodeGen/SPARC/32abi.ll140
-rw-r--r--test/CodeGen/SPARC/64abi.ll185
-rw-r--r--test/CodeGen/SPARC/LeonFixCALLPassUT.ll20
-rwxr-xr-xtest/CodeGen/SPARC/LeonFixFSMULDPassUT.ll31
-rw-r--r--test/CodeGen/SPARC/LeonInsertNOPLoad.ll13
-rwxr-xr-xtest/CodeGen/SPARC/LeonInsertNOPLoadPassUT.ll43
-rw-r--r--test/CodeGen/SPARC/LeonInsertNOPsDoublePrecision.ll17
-rw-r--r--test/CodeGen/SPARC/LeonItinerariesUT.ll50
-rw-r--r--test/CodeGen/SPARC/LeonPreventRoundChangePassUT.ll65
-rwxr-xr-xtest/CodeGen/SPARC/LeonReplaceFMULSPassUT.ll19
-rw-r--r--test/CodeGen/SPARC/LeonReplaceSDIVPassUT.ll9
-rwxr-xr-xtest/CodeGen/SPARC/LeonSMACUMACInstructionUT.ll20
-rw-r--r--test/CodeGen/SPARC/atomics.ll170
-rw-r--r--test/CodeGen/SPARC/float.ll9
-rw-r--r--test/CodeGen/SPARC/fp128.ll117
-rw-r--r--test/CodeGen/SPARC/func-addr.ll51
-rw-r--r--test/CodeGen/SPARC/inlineasm.ll12
-rw-r--r--test/CodeGen/SPARC/missinglabel.ll4
-rwxr-xr-xtest/CodeGen/SPARC/sjlj.ll88
-rw-r--r--test/CodeGen/SPARC/soft-float.ll235
-rw-r--r--test/CodeGen/SPARC/stack-protector.ll33
-rw-r--r--test/CodeGen/SPARC/thread-pointer.ll11
-rw-r--r--test/CodeGen/SPARC/vector-call.ll33
-rw-r--r--test/CodeGen/SPARC/zerostructcall.ll51
25 files changed, 1255 insertions, 175 deletions
diff --git a/test/CodeGen/SPARC/2011-01-11-CC.ll b/test/CodeGen/SPARC/2011-01-11-CC.ll
index 6ea78dd7e1697..6b738e386c3a4 100755
--- a/test/CodeGen/SPARC/2011-01-11-CC.ll
+++ b/test/CodeGen/SPARC/2011-01-11-CC.ll
@@ -70,7 +70,7 @@ entry:
;V8: {{fbe|fbne}}
;V9-LABEL: test_select_int_fcc:
;V9: fcmps
-;V9-NEXT-NOT: nop
+;V9-NOT: nop
;V9-NOT: {{fbe|fbne}}
;V9: mov{{e|ne}} %fcc0
%0 = fcmp une float %f, 0.000000e+00
@@ -101,7 +101,7 @@ entry:
;V8: {{fbne|fbe}}
;V9-LABEL: test_select_dfp_fcc:
;V9: fcmpd
-;V9-NEXT-NOT: nop
+;V9-NOT: nop
;V9-NOT: {{fbne|fbe}}
;V9: fmovd{{e|ne}} %fcc0
%0 = fcmp une double %f, 0.000000e+00
diff --git a/test/CodeGen/SPARC/32abi.ll b/test/CodeGen/SPARC/32abi.ll
index 7ac1de5c09049..09e7a3a09d869 100644
--- a/test/CodeGen/SPARC/32abi.ll
+++ b/test/CodeGen/SPARC/32abi.ll
@@ -1,5 +1,6 @@
-; RUN: llc < %s -march=sparc -disable-sparc-delay-filler -disable-sparc-leaf-proc | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-BE
-; RUN: llc < %s -march=sparcel -disable-sparc-delay-filler -disable-sparc-leaf-proc | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-LE
+; RUN: llc < %s -march=sparc -disable-sparc-delay-filler -disable-sparc-leaf-proc | FileCheck %s --check-prefix=CHECK --check-prefix=HARD --check-prefix=CHECK-BE
+; RUN: llc < %s -march=sparcel -disable-sparc-delay-filler -disable-sparc-leaf-proc | FileCheck %s --check-prefix=CHECK --check-prefix=HARD --check-prefix=CHECK-LE
+; RUN: llc < %s -march=sparc -disable-sparc-delay-filler -disable-sparc-leaf-proc -mattr=soft-float | FileCheck %s --check-prefix=CHECK --check-prefix=SOFT --check-prefix=CHECK-BE
; CHECK-LABEL: intarg:
; The save/restore frame is not strictly necessary here, but we would need to
@@ -55,29 +56,82 @@ define void @call_intarg(i32 %i0, i8* %i1) {
;; straddling the boundary of regs and mem, and floats in regs and mem.
;
; CHECK-LABEL: floatarg:
-; CHECK: save %sp, -120, %sp
-; CHECK: mov %i5, %g2
-; CHECK-NEXT: ld [%fp+92], %g3
-; CHECK-NEXT: mov %i4, %i5
-; CHECK-NEXT: std %g2, [%fp+-24]
-; CHECK-NEXT: mov %i3, %i4
-; CHECK-NEXT: std %i4, [%fp+-16]
-; CHECK-NEXT: std %i0, [%fp+-8]
-; CHECK-NEXT: st %i2, [%fp+-28]
-; CHECK-NEXT: ld [%fp+104], %f0
-; CHECK-NEXT: ldd [%fp+96], %f2
-; CHECK-NEXT: ld [%fp+-28], %f1
-; CHECK-NEXT: ldd [%fp+-8], %f4
-; CHECK-NEXT: ldd [%fp+-16], %f6
-; CHECK-NEXT: ldd [%fp+-24], %f8
-; CHECK-NEXT: fstod %f1, %f10
-; CHECK-NEXT: faddd %f4, %f10, %f4
-; CHECK-NEXT: faddd %f6, %f4, %f4
-; CHECK-NEXT: faddd %f8, %f4, %f4
-; CHECK-NEXT: faddd %f2, %f4, %f2
-; CHECK-NEXT: fstod %f0, %f0
-; CHECK-NEXT: faddd %f0, %f2, %f0
-; CHECK-NEXT: restore
+; HARD: save %sp, -120, %sp
+; HARD: mov %i5, %g2
+; HARD-NEXT: ld [%fp+92], %g3
+; HARD-NEXT: mov %i4, %i5
+; HARD-NEXT: ! kill
+; HARD-NEXT: std %g2, [%fp+-24]
+; HARD-NEXT: mov %i3, %i4
+; HARD-NEXT: std %i4, [%fp+-16]
+; HARD-NEXT: ! kill
+; HARD-NEXT: std %i0, [%fp+-8]
+; HARD-NEXT: st %i2, [%fp+-28]
+; HARD-NEXT: ld [%fp+104], %f0
+; HARD-NEXT: ldd [%fp+96], %f2
+; HARD-NEXT: ld [%fp+-28], %f1
+; HARD-NEXT: ldd [%fp+-8], %f4
+; HARD-NEXT: ldd [%fp+-16], %f6
+; HARD-NEXT: ldd [%fp+-24], %f8
+; HARD-NEXT: fstod %f1, %f10
+; HARD-NEXT: faddd %f4, %f10, %f4
+; HARD-NEXT: faddd %f6, %f4, %f4
+; HARD-NEXT: faddd %f8, %f4, %f4
+; HARD-NEXT: faddd %f2, %f4, %f2
+; HARD-NEXT: fstod %f0, %f0
+; HARD-NEXT: faddd %f0, %f2, %f0
+; SOFT: save %sp, -96, %sp
+; SOFT: ld [%fp+104], %l0
+; SOFT-NEXT: ld [%fp+96], %l1
+; SOFT-NEXT: ld [%fp+100], %l2
+; SOFT-NEXT: ld [%fp+92], %l3
+; SOFT-NEXT: mov %i2, %o0
+; SOFT-NEXT: call __extendsfdf2
+; SOFT-NEXT: nop
+; SOFT-NEXT: mov %o0, %i2
+; SOFT-NEXT: mov %o1, %g2
+; SOFT-NEXT: mov %i0, %o0
+; SOFT-NEXT: mov %i1, %o1
+; SOFT-NEXT: mov %i2, %o2
+; SOFT-NEXT: mov %g2, %o3
+; SOFT-NEXT: call __adddf3
+; SOFT-NEXT: nop
+; SOFT-NEXT: mov %o0, %i0
+; SOFT-NEXT: mov %o1, %i1
+; SOFT-NEXT: mov %i3, %o0
+; SOFT-NEXT: mov %i4, %o1
+; SOFT-NEXT: mov %i0, %o2
+; SOFT-NEXT: mov %i1, %o3
+; SOFT-NEXT: call __adddf3
+; SOFT-NEXT: nop
+; SOFT-NEXT: mov %o0, %i0
+; SOFT-NEXT: mov %o1, %i1
+; SOFT-NEXT: mov %i5, %o0
+; SOFT-NEXT: mov %l3, %o1
+; SOFT-NEXT: mov %i0, %o2
+; SOFT-NEXT: mov %i1, %o3
+; SOFT-NEXT: call __adddf3
+; SOFT-NEXT: nop
+; SOFT-NEXT: mov %o0, %i0
+; SOFT-NEXT: mov %o1, %i1
+; SOFT-NEXT: mov %l1, %o0
+; SOFT-NEXT: mov %l2, %o1
+; SOFT-NEXT: mov %i0, %o2
+; SOFT-NEXT: mov %i1, %o3
+; SOFT-NEXT: call __adddf3
+; SOFT-NEXT: nop
+; SOFT-NEXT: mov %o0, %i0
+; SOFT-NEXT: mov %o1, %i1
+; SOFT-NEXT: mov %l0, %o0
+; SOFT-NEXT: call __extendsfdf2
+; SOFT-NEXT: nop
+; SOFT-NEXT: mov %i0, %o2
+; SOFT-NEXT: mov %i1, %o3
+; SOFT-NEXT: call __adddf3
+; SOFT-NEXT: nop
+; SOFT-NEXT: mov %o0, %i0
+; SOFT-NEXT: mov %o1, %i1
+; CHECK: restore
define double @floatarg(double %a0, ; %i0,%i1
float %a1, ; %i2
double %a2, ; %i3, %i4
@@ -95,18 +149,30 @@ define double @floatarg(double %a0, ; %i0,%i1
}
; CHECK-LABEL: call_floatarg:
-; CHECK: save %sp, -112, %sp
-; CHECK: mov %i2, %o1
-; CHECK-NEXT: mov %i1, %o0
-; CHECK-NEXT: st %i0, [%sp+104]
-; CHECK-NEXT: std %o0, [%sp+96]
-; CHECK-NEXT: st %o1, [%sp+92]
-; CHECK-NEXT: mov %i0, %o2
-; CHECK-NEXT: mov %o0, %o3
-; CHECK-NEXT: mov %o1, %o4
-; CHECK-NEXT: mov %o0, %o5
-; CHECK-NEXT: call floatarg
-; CHECK: std %f0, [%i4]
+; HARD: save %sp, -112, %sp
+; HARD: mov %i2, %o1
+; HARD-NEXT: mov %i1, %o0
+; HARD-NEXT: st %i0, [%sp+104]
+; HARD-NEXT: std %o0, [%sp+96]
+; HARD-NEXT: st %o1, [%sp+92]
+; HARD-NEXT: mov %i0, %o2
+; HARD-NEXT: mov %o0, %o3
+; HARD-NEXT: mov %o1, %o4
+; HARD-NEXT: mov %o0, %o5
+; HARD-NEXT: call floatarg
+; HARD: std %f0, [%i4]
+; SOFT: st %i0, [%sp+104]
+; SOFT-NEXT: st %i2, [%sp+100]
+; SOFT-NEXT: st %i1, [%sp+96]
+; SOFT-NEXT: st %i2, [%sp+92]
+; SOFT-NEXT: mov %i1, %o0
+; SOFT-NEXT: mov %i2, %o1
+; SOFT-NEXT: mov %i0, %o2
+; SOFT-NEXT: mov %i1, %o3
+; SOFT-NEXT: mov %i2, %o4
+; SOFT-NEXT: mov %i1, %o5
+; SOFT-NEXT: call floatarg
+; SOFT: std %o0, [%i4]
; CHECK: restore
define void @call_floatarg(float %f1, double %d2, float %f5, double *%p) {
%r = call double @floatarg(double %d2, float %f1, double %d2, double %d2,
diff --git a/test/CodeGen/SPARC/64abi.ll b/test/CodeGen/SPARC/64abi.ll
index 96104ecc3c68c..b963be2e9853d 100644
--- a/test/CodeGen/SPARC/64abi.ll
+++ b/test/CodeGen/SPARC/64abi.ll
@@ -1,4 +1,5 @@
-; RUN: llc < %s -march=sparcv9 -disable-sparc-delay-filler -disable-sparc-leaf-proc | FileCheck %s
+; RUN: llc < %s -march=sparcv9 -disable-sparc-delay-filler -disable-sparc-leaf-proc | FileCheck %s --check-prefix=CHECK --check-prefix=HARD
+; RUN: llc < %s -march=sparcv9 -disable-sparc-delay-filler -disable-sparc-leaf-proc -mattr=soft-float | FileCheck %s --check-prefix=CHECK --check-prefix=SOFT
; CHECK-LABEL: intarg:
; The save/restore frame is not strictly necessary here, but we would need to
@@ -54,13 +55,22 @@ define void @call_intarg(i32 %i0, i8* %i1) {
}
; CHECK-LABEL: floatarg:
-; CHECK: save %sp, -128, %sp
-; CHECK: ld [%fp+2307], [[F:%f[0-9]+]]
-; CHECK: fstod %f1,
-; CHECK: faddd %f2,
-; CHECK: faddd %f4,
-; CHECK: faddd %f6,
-; CHECK: fadds %f31, [[F]]
+; HARD: save %sp, -128, %sp
+; HARD: ld [%fp+2307], [[F:%f[0-9]+]]
+; HARD: fstod %f1,
+; HARD: faddd %f2,
+; HARD: faddd %f4,
+; HARD: faddd %f6,
+; HARD: fadds %f31, [[F]]
+; SOFT: save %sp, -176, %sp
+; SOFT: srl %i0, 0, %o0
+; SOFT-NEXT: call __extendsfdf2
+; SOFT: mov %o0, %i0
+; SOFT: mov %i1, %o0
+; SOFT: mov %i2, %o0
+; SOFT: mov %i3, %o0
+; SOFT: ld [%fp+2299], %o0
+; SOFT: ld [%fp+2307], %o1
define double @floatarg(float %a0, ; %f1
double %a1, ; %d2
double %a2, ; %d4
@@ -92,13 +102,32 @@ define double @floatarg(float %a0, ; %f1
; CHECK-LABEL: call_floatarg:
; CHECK: save %sp, -272, %sp
; Store 8 bytes in full slot.
-; CHECK: std %f2, [%sp+2311]
+; HARD: std %f2, [%sp+2311]
; Store 4 bytes, right-aligned in slot.
-; CHECK: st %f1, [%sp+2307]
-; CHECK: fmovd %f2, %f4
+; HARD: st %f1, [%sp+2307]
+; HARD: fmovd %f2, %f4
+; SOFT: stx %i1, [%sp+2311]
+; SOFT: stx %i0, [%sp+2303]
+; SOFT: stx %i2, [%sp+2295]
+; SOFT: stx %i2, [%sp+2287]
+; SOFT: stx %i2, [%sp+2279]
+; SOFT: stx %i2, [%sp+2271]
+; SOFT: stx %i2, [%sp+2263]
+; SOFT: stx %i2, [%sp+2255]
+; SOFT: stx %i2, [%sp+2247]
+; SOFT: stx %i2, [%sp+2239]
+; SOFT: stx %i2, [%sp+2231]
+; SOFT: stx %i2, [%sp+2223]
+; SOFT: mov %i2, %o0
+; SOFT: mov %i1, %o1
+; SOFT: mov %i1, %o2
+; SOFT: mov %i1, %o3
+; SOFT: mov %i2, %o4
+; SOFT: mov %i2, %o5
; CHECK: call floatarg
; CHECK-NOT: add %sp
; CHECK: restore
+
define void @call_floatarg(float %f1, double %d2, float %f5, double *%p) {
%r = call double @floatarg(float %f5, double %d2, double %d2, double %d2,
float %f5, float %f5, float %f5, float %f5,
@@ -112,9 +141,21 @@ define void @call_floatarg(float %f1, double %d2, float %f5, double *%p) {
; CHECK-LABEL: mixedarg:
; CHECK: ldx [%fp+2247]
; CHECK: ldx [%fp+2231]
-; CHECK: fstod %f3
-; CHECK: faddd %f6
-; CHECK: faddd %f16
+; SOFT: ldx [%fp+2239], %i0
+; HARD: fstod %f3
+; HARD: faddd %f6
+; HARD: faddd %f16
+; SOFT: mov %o0, %i1
+; SOFT-NEXT: mov %i3, %o0
+; SOFT-NEXT: mov %i1, %o1
+; SOFT-NEXT: call __adddf3
+; SOFT: mov %o0, %i1
+; SOFT-NEXT: mov %i0, %o0
+; SOFT-NEXT: mov %i1, %o1
+; SOFT-NEXT: call __adddf3
+; HARD: std %f0, [%i1]
+; SOFT: stx %o0, [%i5]
+
define void @mixedarg(i8 %a0, ; %i0
float %a1, ; %f3
i16 %a2, ; %i2
@@ -135,12 +176,15 @@ define void @mixedarg(i8 %a0, ; %i0
; CHECK-LABEL: call_mixedarg:
; CHECK: stx %i2, [%sp+2247]
+; SOFT: stx %i1, [%sp+2239]
; CHECK: stx %i0, [%sp+2223]
-; CHECK: fmovd %f2, %f6
-; CHECK: fmovd %f2, %f16
+; HARD: fmovd %f2, %f6
+; HARD: fmovd %f2, %f16
+; SOFT: mov %i1, %o3
; CHECK: call mixedarg
; CHECK-NOT: add %sp
; CHECK: restore
+
define void @call_mixedarg(i64 %i0, double %f2, i16* %i2) {
call void @mixedarg(i8 undef,
float undef,
@@ -158,8 +202,10 @@ define void @call_mixedarg(i64 %i0, double %f2, i16* %i2) {
; The inreg attribute is used to indicate 32-bit sized struct elements that
; share an 8-byte slot.
; CHECK-LABEL: inreg_fi:
-; CHECK: fstoi %f1
-; CHECK: srlx %i0, 32, [[R:%[gilo][0-7]]]
+; SOFT: srlx %i0, 32, [[R:%[gilo][0-7]]]
+; HARD: fstoi %f1
+; SOFT: call __fixsfsi
+; HARD: srlx %i0, 32, [[R:%[gilo][0-7]]]
; CHECK: sub [[R]],
define i32 @inreg_fi(i32 inreg %a0, ; high bits of %i0
float inreg %a1) { ; %f1
@@ -171,8 +217,11 @@ define i32 @inreg_fi(i32 inreg %a0, ; high bits of %i0
; CHECK-LABEL: call_inreg_fi:
; Allocate space for 6 arguments, even when only 2 are used.
; CHECK: save %sp, -176, %sp
-; CHECK: sllx %i1, 32, %o0
-; CHECK: fmovs %f5, %f1
+; HARD: sllx %i1, 32, %o0
+; HARD: fmovs %f5, %f1
+; SOFT: srl %i2, 0, %i0
+; SOFT: sllx %i1, 32, %i1
+; SOFT: or %i1, %i0, %o0
; CHECK: call inreg_fi
define void @call_inreg_fi(i32* %p, i32 %i1, float %f5) {
%x = call i32 @inreg_fi(i32 %i1, float %f5)
@@ -180,7 +229,10 @@ define void @call_inreg_fi(i32* %p, i32 %i1, float %f5) {
}
; CHECK-LABEL: inreg_ff:
-; CHECK: fsubs %f0, %f1, %f0
+; HARD: fsubs %f0, %f1, %f0
+; SOFT: srlx %i0, 32, %o0
+; SOFT: srl %i0, 0, %o1
+; SOFT: call __subsf3
define float @inreg_ff(float inreg %a0, ; %f0
float inreg %a1) { ; %f1
%rv = fsub float %a0, %a1
@@ -188,8 +240,11 @@ define float @inreg_ff(float inreg %a0, ; %f0
}
; CHECK-LABEL: call_inreg_ff:
-; CHECK: fmovs %f3, %f0
-; CHECK: fmovs %f5, %f1
+; HARD: fmovs %f3, %f0
+; HARD: fmovs %f5, %f1
+; SOFT: srl %i2, 0, %i0
+; SOFT: sllx %i1, 32, %i1
+; SOFT: or %i1, %i0, %o0
; CHECK: call inreg_ff
define void @call_inreg_ff(i32* %p, float %f3, float %f5) {
%x = call float @inreg_ff(float %f3, float %f5)
@@ -197,7 +252,9 @@ define void @call_inreg_ff(i32* %p, float %f3, float %f5) {
}
; CHECK-LABEL: inreg_if:
-; CHECK: fstoi %f0
+; HARD: fstoi %f0
+; SOFT: srlx %i0, 32, %o0
+; SOFT: call __fixsfsi
; CHECK: sub %i0
define i32 @inreg_if(float inreg %a0, ; %f0
i32 inreg %a1) { ; low bits of %i0
@@ -207,8 +264,11 @@ define i32 @inreg_if(float inreg %a0, ; %f0
}
; CHECK-LABEL: call_inreg_if:
-; CHECK: fmovs %f3, %f0
-; CHECK: mov %i2, %o0
+; HARD: fmovs %f3, %f0
+; HARD: mov %i2, %o0
+; SOFT: srl %i2, 0, %i0
+; SOFT: sllx %i1, 32, %i1
+; SOFT: or %i1, %i0, %o0
; CHECK: call inreg_if
define void @call_inreg_if(i32* %p, float %f3, i32 %i2) {
%x = call i32 @inreg_if(float %f3, i32 %i2)
@@ -265,7 +325,8 @@ define void @call_ret_i64_pair(i64* %i0) {
; This is not a C struct, the i32 member uses 8 bytes, but the float only 4.
; CHECK-LABEL: ret_i32_float_pair:
; CHECK: ld [%i2], %i0
-; CHECK: ld [%i3], %f2
+; HARD: ld [%i3], %f2
+; SOFT: ld [%i3], %i1
define { i32, float } @ret_i32_float_pair(i32 %a0, i32 %a1,
i32* %p, float* %q) {
%r1 = load i32, i32* %p
@@ -279,7 +340,8 @@ define { i32, float } @ret_i32_float_pair(i32 %a0, i32 %a1,
; CHECK-LABEL: call_ret_i32_float_pair:
; CHECK: call ret_i32_float_pair
; CHECK: st %o0, [%i0]
-; CHECK: st %f2, [%i1]
+; HARD: st %f2, [%i1]
+; SOFT: st %o1, [%i1]
define void @call_ret_i32_float_pair(i32* %i0, float* %i1) {
%rv = call { i32, float } @ret_i32_float_pair(i32 undef, i32 undef,
i32* undef, float* undef)
@@ -293,7 +355,8 @@ define void @call_ret_i32_float_pair(i32* %i0, float* %i1) {
; This is a C struct, each member uses 4 bytes.
; CHECK-LABEL: ret_i32_float_packed:
; CHECK: ld [%i2], [[R:%[gilo][0-7]]]
-; CHECK: ld [%i3], %f1
+; HARD: ld [%i3], %f1
+; SOFT: ld [%i3], %i1
; CHECK: sllx [[R]], 32, %i0
define inreg { i32, float } @ret_i32_float_packed(i32 %a0, i32 %a1,
i32* %p, float* %q) {
@@ -309,7 +372,8 @@ define inreg { i32, float } @ret_i32_float_packed(i32 %a0, i32 %a1,
; CHECK: call ret_i32_float_packed
; CHECK: srlx %o0, 32, [[R:%[gilo][0-7]]]
; CHECK: st [[R]], [%i0]
-; CHECK: st %f1, [%i1]
+; HARD: st %f1, [%i1]
+; SOFT: st %o0, [%i1]
define void @call_ret_i32_float_packed(i32* %i0, float* %i1) {
%rv = call { i32, float } @ret_i32_float_packed(i32 undef, i32 undef,
i32* undef, float* undef)
@@ -413,13 +477,21 @@ entry:
declare i32 @use_buf(i32, i8*)
; CHECK-LABEL: test_fp128_args:
-; CHECK-DAG: std %f0, [%fp+{{.+}}]
-; CHECK-DAG: std %f2, [%fp+{{.+}}]
-; CHECK-DAG: std %f6, [%fp+{{.+}}]
-; CHECK-DAG: std %f4, [%fp+{{.+}}]
-; CHECK: add %fp, [[Offset:[0-9]+]], %o0
-; CHECK: call _Qp_add
-; CHECK: ldd [%fp+[[Offset]]], %f0
+; HARD-DAG: std %f0, [%fp+{{.+}}]
+; HARD-DAG: std %f2, [%fp+{{.+}}]
+; HARD-DAG: std %f6, [%fp+{{.+}}]
+; HARD-DAG: std %f4, [%fp+{{.+}}]
+; HARD: add %fp, [[Offset:[0-9]+]], %o0
+; HARD: call _Qp_add
+; HARD: ldd [%fp+[[Offset]]], %f0
+; SOFT-DAG: mov %i0, %o0
+; SOFT-DAG: mov %i1, %o1
+; SOFT-DAG: mov %i2, %o2
+; SOFT-DAG: mov %i3, %o3
+; SOFT: call __addtf3
+; SOFT: mov %o0, %i0
+; SOFT: mov %o1, %i1
+
define fp128 @test_fp128_args(fp128 %a, fp128 %b) {
entry:
%0 = fadd fp128 %a, %b
@@ -429,11 +501,14 @@ entry:
declare i64 @receive_fp128(i64 %a, ...)
; CHECK-LABEL: test_fp128_variable_args:
-; CHECK-DAG: std %f4, [%sp+[[Offset0:[0-9]+]]]
-; CHECK-DAG: std %f6, [%sp+[[Offset1:[0-9]+]]]
-; CHECK-DAG: ldx [%sp+[[Offset0]]], %o2
-; CHECK-DAG: ldx [%sp+[[Offset1]]], %o3
-; CHECK: call receive_fp128
+; HARD-DAG: std %f4, [%sp+[[Offset0:[0-9]+]]]
+; HARD-DAG: std %f6, [%sp+[[Offset1:[0-9]+]]]
+; HARD-DAG: ldx [%sp+[[Offset0]]], %o2
+; HARD-DAG: ldx [%sp+[[Offset1]]], %o3
+; SOFT-DAG: mov %i0, %o0
+; SOFT-DAG: mov %i1, %o1
+; SOFT-DAG: mov %i2, %o2
+; CHECK: call receive_fp128
define i64 @test_fp128_variable_args(i64 %a, fp128 %b) {
entry:
%0 = call i64 (i64, ...) @receive_fp128(i64 %a, fp128 %b)
@@ -441,14 +516,22 @@ entry:
}
; CHECK-LABEL: test_call_libfunc:
-; CHECK: st %f1, [%fp+[[Offset0:[0-9]+]]]
-; CHECK: fmovs %f3, %f1
-; CHECK: call cosf
-; CHECK: st %f0, [%fp+[[Offset1:[0-9]+]]]
-; CHECK: ld [%fp+[[Offset0]]], %f1
-; CHECK: call sinf
-; CHECK: ld [%fp+[[Offset1]]], %f1
-; CHECK: fmuls %f1, %f0, %f0
+; HARD: st %f1, [%fp+[[Offset0:[0-9]+]]]
+; HARD: fmovs %f3, %f1
+; SOFT: srl %i1, 0, %o0
+; CHECK: call cosf
+; HARD: st %f0, [%fp+[[Offset1:[0-9]+]]]
+; HARD: ld [%fp+[[Offset0]]], %f1
+; SOFT: mov %o0, %i1
+; SOFT: srl %i0, 0, %o0
+; CHECK: call sinf
+; HARD: ld [%fp+[[Offset1]]], %f1
+; HARD: fmuls %f1, %f0, %f0
+; SOFT: mov %o0, %i0
+; SOFT: mov %i1, %o0
+; SOFT: mov %i0, %o1
+; SOFT: call __mulsf3
+; SOFT: sllx %o0, 32, %i0
define inreg float @test_call_libfunc(float %arg0, float %arg1) {
entry:
@@ -460,5 +543,3 @@ entry:
declare inreg float @cosf(float %arg) readnone nounwind
declare inreg float @sinf(float %arg) readnone nounwind
-
-
diff --git a/test/CodeGen/SPARC/LeonFixCALLPassUT.ll b/test/CodeGen/SPARC/LeonFixCALLPassUT.ll
new file mode 100644
index 0000000000000..697590be40662
--- /dev/null
+++ b/test/CodeGen/SPARC/LeonFixCALLPassUT.ll
@@ -0,0 +1,20 @@
+; RUN: llc %s -O0 -march=sparc -mcpu=at697e -o - | FileCheck %s -check-prefix=FIXCALL
+; RUN: llc %s -O0 -march=sparc -mcpu=leon2 -mattr=+fixcall -o - | FileCheck %s -check-prefix=FIXCALL
+
+; RUN: llc %s -O0 -march=sparc -mcpu=at697e -mattr=-fixcall -o - | FileCheck %s -check-prefix=NO_FIXCALL
+; RUN: llc %s -O0 -march=sparc -mcpu=leon2 -o - | FileCheck %s -check-prefix=NO_FIXCALL
+
+
+; FIXCALL-LABEL: immediate_call_test
+; FIXCALL: call 763288
+
+; NO_FIXCALL-LABEL: immediate_call_test
+; NO_FIXCALL: call 2047583640
+define void @immediate_call_test() nounwind {
+entry:
+ call void asm sideeffect "call $0", "i"(i32 2047583640) nounwind
+ ret void
+}
+
+
+
diff --git a/test/CodeGen/SPARC/LeonFixFSMULDPassUT.ll b/test/CodeGen/SPARC/LeonFixFSMULDPassUT.ll
new file mode 100755
index 0000000000000..e2f2323a049c0
--- /dev/null
+++ b/test/CodeGen/SPARC/LeonFixFSMULDPassUT.ll
@@ -0,0 +1,31 @@
+; RUN: llc %s -O0 -march=sparc -mcpu=ut699 -o - | FileCheck %s
+
+; CHECK-LABEL: test_fix_fsmuld_1
+; CHECK: fstod %f20, %f2
+; CHECK: fstod %f21, %f3
+; CHECK: fmuld %f2, %f3, %f8
+; CHECK: fstod %f20, %f0
+define double @test_fix_fsmuld_1() {
+entry:
+ %a = alloca float, align 4
+ %b = alloca float, align 4
+ store float 0x402ECCCCC0000000, float* %a, align 4
+ store float 0x4022333340000000, float* %b, align 4
+ %0 = load float, float* %b, align 4
+ %1 = load float, float* %a, align 4
+ %mul = tail call double asm sideeffect "fsmuld $0, $1, $2", "={f20},{f21},{f8}"(float* %a, float* %b)
+
+ ret double %mul
+}
+
+; CHECK-LABEL: test_fix_fsmuld_2
+; CHECK: fstod %f20, %f2
+; CHECK: fstod %f21, %f3
+; CHECK: fmuld %f2, %f3, %f8
+; CHECK: fstod %f20, %f0
+define double @test_fix_fsmuld_2(float* %a, float* %b) {
+entry:
+ %mul = tail call double asm sideeffect "fsmuld $0, $1, $2", "={f20},{f21},{f8}"(float* %a, float* %b)
+
+ ret double %mul
+}
diff --git a/test/CodeGen/SPARC/LeonInsertNOPLoad.ll b/test/CodeGen/SPARC/LeonInsertNOPLoad.ll
new file mode 100644
index 0000000000000..315fc85fca386
--- /dev/null
+++ b/test/CodeGen/SPARC/LeonInsertNOPLoad.ll
@@ -0,0 +1,13 @@
+; RUN: llc %s -O0 -march=sparc -mcpu=ut699 -o - | FileCheck %s
+
+; CHECK: ld [%o0+%lo(.LCPI0_0)], %f0
+; CHECK-NEXT: nop
+
+
+define float @X() #0 {
+entry:
+ %f = alloca float, align 4
+ store float 0x3FF3C08320000000, float* %f, align 4
+ %0 = load float, float* %f, align 4
+ ret float %0
+}
diff --git a/test/CodeGen/SPARC/LeonInsertNOPLoadPassUT.ll b/test/CodeGen/SPARC/LeonInsertNOPLoadPassUT.ll
new file mode 100755
index 0000000000000..57ae16227e7d0
--- /dev/null
+++ b/test/CodeGen/SPARC/LeonInsertNOPLoadPassUT.ll
@@ -0,0 +1,43 @@
+; RUN: llc %s -O0 -march=sparc -mcpu=ut699 -o - | FileCheck %s
+; RUN: llc %s -O0 -march=sparc -mcpu=leon3 -mattr=+insertnopload -o - | FileCheck %s
+
+; CHECK-LABEL: ld_float_test
+; CHECK: ld [%o0+%lo(.LCPI0_0)], %f0
+; CHECK-NEXT: nop
+define float @ld_float_test() #0 {
+entry:
+ %f = alloca float, align 4
+ store float 0x3FF3C08320000000, float* %f, align 4
+ %0 = load float, float* %f, align 4
+ ret float %0
+}
+
+; CHECK-LABEL: ld_i32_test
+; CHECK: ld [%o0], %o0
+; CHECK-NEXT: nop
+define i32 @ld_i32_test(i32 *%p) {
+ %res = load i32, i32* %p
+ ret i32 %res
+}
+
+; CHECK-LABEL: ld_inlineasm_test_1
+; CHECK: ld [%o0], %o0
+; CHECK-NEXT: !NO_APP
+; CHECK-NEXT: nop
+define float @ld_inlineasm_test_1(float* %a) {
+entry:
+ %res = tail call float asm sideeffect "ld [$1], $0", "=r,r"(float* %a)
+
+ ret float %res
+}
+
+; CHECK-LABEL: ld_inlineasm_test_2
+; CHECK: ld [%o0], %o0
+; CHECK-NEXT: !NO_APP
+; CHECK-NEXT: nop
+define i32 @ld_inlineasm_test_2(i32* %a) {
+entry:
+ %res = tail call i32 asm sideeffect "ld [$1], $0", "=r,r"(i32* %a)
+
+ ret i32 %res
+} \ No newline at end of file
diff --git a/test/CodeGen/SPARC/LeonInsertNOPsDoublePrecision.ll b/test/CodeGen/SPARC/LeonInsertNOPsDoublePrecision.ll
new file mode 100644
index 0000000000000..0ee3d9071a995
--- /dev/null
+++ b/test/CodeGen/SPARC/LeonInsertNOPsDoublePrecision.ll
@@ -0,0 +1,17 @@
+; RUN: llc %s -O0 -march=sparc -mcpu=at697f -o - | FileCheck %s
+
+; CHECK: ldd
+; CHECK: ldd
+; CHECK-NEXT: nop
+
+define double @mult() #0 {
+entry:
+ %x = alloca double, align 8
+ %y = alloca double, align 8
+ store double 3.141590e+00, double* %x, align 8
+ store double 1.234560e+00, double* %y, align 8
+ %0 = load double, double* %x, align 8
+ %1 = load double, double* %y, align 8
+ %mul = fmul double %0, %1
+ ret double %mul
+}
diff --git a/test/CodeGen/SPARC/LeonItinerariesUT.ll b/test/CodeGen/SPARC/LeonItinerariesUT.ll
new file mode 100644
index 0000000000000..87e0c4621c084
--- /dev/null
+++ b/test/CodeGen/SPARC/LeonItinerariesUT.ll
@@ -0,0 +1,50 @@
+; RUN: llc < %s -O1 -march=sparc | FileCheck %s -check-prefix=NO_ITIN
+; RUN: llc < %s -O1 -march=sparc -mcpu=leon2 | FileCheck %s -check-prefix=LEON2_ITIN
+; RUN: llc < %s -O1 -march=sparc -mcpu=leon3 | FileCheck %s -check-prefix=LEON3_4_ITIN
+; RUN: llc < %s -O1 -march=sparc -mcpu=leon4 | FileCheck %s -check-prefix=LEON3_4_ITIN
+
+; NO_ITIN-LABEL: f32_ops:
+; NO_ITIN: ld
+; NO_ITIN-NEXT: ld
+; NO_ITIN-NEXT: ld
+; NO_ITIN-NEXT: ld
+; NO_ITIN-NEXT: fadds
+; NO_ITIN-NEXT: fsubs
+; NO_ITIN-NEXT: fmuls
+; NO_ITIN-NEXT: retl
+; NO_ITIN-NEXT: fdivs
+
+; LEON2_ITIN-LABEL: f32_ops:
+; LEON2_ITIN: ld
+; LEON2_ITIN-NEXT: ld
+; LEON2_ITIN-NEXT: fadds
+; LEON2_ITIN-NEXT: ld
+; LEON2_ITIN-NEXT: fsubs
+; LEON2_ITIN-NEXT: ld
+; LEON2_ITIN-NEXT: fmuls
+; LEON2_ITIN-NEXT: retl
+; LEON2_ITIN-NEXT: fdivs
+
+; LEON3_4_ITIN-LABEL: f32_ops:
+; LEON3_4_ITIN: ld
+; LEON3_4_ITIN-NEXT: ld
+; LEON3_4_ITIN-NEXT: ld
+; LEON3_4_ITIN-NEXT: fadds
+; LEON3_4_ITIN-NEXT: ld
+; LEON3_4_ITIN-NEXT: fsubs
+; LEON3_4_ITIN-NEXT: fmuls
+; LEON3_4_ITIN-NEXT: retl
+; LEON3_4_ITIN-NEXT: fdivs
+
+define float @f32_ops(float* byval %a, float* byval %b, float* byval %c, float* byval %d) {
+entry:
+ %0 = load float, float* %a, align 8
+ %1 = load float, float* %b, align 8
+ %2 = load float, float* %c, align 8
+ %3 = load float, float* %d, align 8
+ %4 = fadd float %0, %1
+ %5 = fsub float %4, %2
+ %6 = fmul float %5, %3
+ %7 = fdiv float %6, %4
+ ret float %7
+} \ No newline at end of file
diff --git a/test/CodeGen/SPARC/LeonPreventRoundChangePassUT.ll b/test/CodeGen/SPARC/LeonPreventRoundChangePassUT.ll
new file mode 100644
index 0000000000000..07172fdb9451a
--- /dev/null
+++ b/test/CodeGen/SPARC/LeonPreventRoundChangePassUT.ll
@@ -0,0 +1,65 @@
+; RUN: llc %s -O0 -march=sparc -mcpu=ut699 -o - | FileCheck %s -check-prefix=NO_ROUND_FUNC
+; RUN: llc %s -O0 -march=sparc -mcpu=leon3 -mattr=+prvntroundchange -o - | FileCheck %s -check-prefix=NO_ROUND_FUNC
+
+; RUN: llc %s -O0 -march=sparc -mcpu=ut699 -mattr=-prvntroundchange -o - | FileCheck %s -check-prefix=ROUND_FUNC
+; RUN: llc %s -O0 -march=sparc -mcpu=leon3 -o - | FileCheck %s -check-prefix=ROUND_FUNC
+
+
+; NO_ROUND_FUNC-LABEL: test_round_change
+; NO_ROUND_FUNC-NOT: fesetround
+
+; ROUND_FUNC-LABEL: test_round_change
+; ROUND_FUNC: fesetround
+
+; ModuleID = '<stdin>'
+target datalayout = "E-m:e-p:32:32-i64:64-f128:64-n32-S64"
+target triple = "sparc-unknown--eabi"
+
+@.str = private unnamed_addr constant [17 x i8] c"-((-a)*b) != a*b\00", align 1
+@.str.1 = private unnamed_addr constant [7 x i8] c"test.c\00", align 1
+@__PRETTY_FUNCTION__.mult = private unnamed_addr constant [12 x i8] c"void mult()\00", align 1
+
+; Function Attrs: nounwind
+define void @test_round_change() #0 {
+entry:
+ %a = alloca double, align 8
+ %b = alloca double, align 8
+ %x = alloca float, align 4
+ store double 1.100000e+00, double* %a, align 8
+ store double 1.010000e+01, double* %b, align 8
+ store float 0x400921FA00000000, float* %x, align 4
+ %call = call i32 @fesetround(i32 2048) #2
+ %0 = load double, double* %a, align 8
+ %sub = fsub double -0.000000e+00, %0
+ %1 = load double, double* %b, align 8
+ %mul = fmul double %sub, %1
+ %sub1 = fsub double -0.000000e+00, %mul
+ %2 = load double, double* %a, align 8
+ %3 = load double, double* %b, align 8
+ %mul2 = fmul double %2, %3
+ %cmp = fcmp une double %sub1, %mul2
+ br i1 %cmp, label %cond.true, label %cond.false
+
+cond.true: ; preds = %entry
+ br label %cond.end
+
+cond.false: ; preds = %entry
+ call void @__assert_fail(i8* getelementptr inbounds ([17 x i8], [17 x i8]* @.str, i32 0, i32 0), i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.1, i32 0, i32 0), i32 10, i8* getelementptr inbounds ([12 x i8], [12 x i8]* @__PRETTY_FUNCTION__.mult, i32 0, i32 0)) #3
+ unreachable
+ ; No predecessors!
+ br label %cond.end
+
+cond.end: ; preds = %4, %cond.true
+ ret void
+}
+
+; Function Attrs: nounwind
+declare i32 @fesetround(i32) #0
+
+; Function Attrs: noreturn nounwind
+declare void @__assert_fail(i8*, i8*, i32, i8*) #1
+
+attributes #0 = { nounwind "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { noreturn nounwind "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #2 = { nounwind }
+attributes #3 = { noreturn nounwind } \ No newline at end of file
diff --git a/test/CodeGen/SPARC/LeonReplaceFMULSPassUT.ll b/test/CodeGen/SPARC/LeonReplaceFMULSPassUT.ll
new file mode 100755
index 0000000000000..7d0950cb1c887
--- /dev/null
+++ b/test/CodeGen/SPARC/LeonReplaceFMULSPassUT.ll
@@ -0,0 +1,19 @@
+; RUN: llc %s -O0 -march=sparc -mcpu=ut699 -o - | FileCheck %s
+
+; CHECK-LABEL: fmuls_fix_test
+; CHECK: fstod %f20, %f2
+; CHECK: fstod %f21, %f3
+; CHECK: fmuld %f2, %f3, %f8
+; CHECK: fstod %f20, %f0
+define double @fmuls_fix_test() {
+entry:
+ %a = alloca float, align 4
+ %b = alloca float, align 4
+ store float 0x402ECCCCC0000000, float* %a, align 4
+ store float 0x4022333340000000, float* %b, align 4
+ %0 = load float, float* %b, align 4
+ %1 = load float, float* %a, align 4
+ %mul = tail call double asm sideeffect "fmuls $0, $1, $2", "={f20},{f21},{f8}"(float* %a, float* %b)
+
+ ret double %mul
+}
diff --git a/test/CodeGen/SPARC/LeonReplaceSDIVPassUT.ll b/test/CodeGen/SPARC/LeonReplaceSDIVPassUT.ll
new file mode 100644
index 0000000000000..67232d777039e
--- /dev/null
+++ b/test/CodeGen/SPARC/LeonReplaceSDIVPassUT.ll
@@ -0,0 +1,9 @@
+; RUN: llc %s -O0 -march=sparc -mcpu=at697e -o - | FileCheck %s
+
+; CHECK: sdivcc %o0, %o1, %o0
+
+define i32 @lbr59(i32 %a, i32 %b)
+{
+ %r = sdiv i32 %a, %b
+ ret i32 %r
+}
diff --git a/test/CodeGen/SPARC/LeonSMACUMACInstructionUT.ll b/test/CodeGen/SPARC/LeonSMACUMACInstructionUT.ll
new file mode 100755
index 0000000000000..281113b58a051
--- /dev/null
+++ b/test/CodeGen/SPARC/LeonSMACUMACInstructionUT.ll
@@ -0,0 +1,20 @@
+; RUN: llc %s -O0 -march=sparc -mcpu=leon2 -o - | FileCheck %s
+; RUN: llc %s -O0 -march=sparc -mcpu=leon3 -o - | FileCheck %s
+; RUN: llc %s -O0 -march=sparc -mcpu=leon4 -o - | FileCheck %s
+
+; CHECK-LABEL: smac_test:
+; CHECK: smac %o1, %o0, %o0
+define i32 @smac_test(i16* %a, i16* %b) {
+entry:
+; %0 = tail call i32 asm sideeffect "smac $2, $1, $0", "={r2},{r3},{r4}"(i16* %a, i16* %b)
+ %0 = tail call i32 asm sideeffect "smac $2, $1, $0", "=r,rI,r"(i16* %a, i16* %b)
+ ret i32 %0
+}
+
+; CHECK-LABEL: umac_test:
+; CHECK: umac %o1, %o0, %o0
+define i32 @umac_test(i16* %a, i16* %b) {
+entry:
+ %0 = tail call i32 asm sideeffect "umac $2, $1, $0", "=r,rI,r"(i16* %a, i16* %b)
+ ret i32 %0
+}
diff --git a/test/CodeGen/SPARC/atomics.ll b/test/CodeGen/SPARC/atomics.ll
index bea9a33746969..5e608e728c372 100644
--- a/test/CodeGen/SPARC/atomics.ll
+++ b/test/CodeGen/SPARC/atomics.ll
@@ -1,5 +1,37 @@
; RUN: llc < %s -march=sparcv9 -verify-machineinstrs | FileCheck %s
+; CHECK-LABEL: test_atomic_i8
+; CHECK: ldub [%o0]
+; CHECK: membar
+; CHECK: ldub [%o1]
+; CHECK: membar
+; CHECK: membar
+; CHECK: stb {{.+}}, [%o2]
+define i8 @test_atomic_i8(i8* %ptr1, i8* %ptr2, i8* %ptr3) {
+entry:
+ %0 = load atomic i8, i8* %ptr1 acquire, align 1
+ %1 = load atomic i8, i8* %ptr2 acquire, align 1
+ %2 = add i8 %0, %1
+ store atomic i8 %2, i8* %ptr3 release, align 1
+ ret i8 %2
+}
+
+; CHECK-LABEL: test_atomic_i16
+; CHECK: lduh [%o0]
+; CHECK: membar
+; CHECK: lduh [%o1]
+; CHECK: membar
+; CHECK: membar
+; CHECK: sth {{.+}}, [%o2]
+define i16 @test_atomic_i16(i16* %ptr1, i16* %ptr2, i16* %ptr3) {
+entry:
+ %0 = load atomic i16, i16* %ptr1 acquire, align 2
+ %1 = load atomic i16, i16* %ptr2 acquire, align 2
+ %2 = add i16 %0, %1
+ store atomic i16 %2, i16* %ptr3 release, align 2
+ ret i16 %2
+}
+
; CHECK-LABEL: test_atomic_i32
; CHECK: ld [%o0]
; CHECK: membar
@@ -9,10 +41,10 @@
; CHECK: st {{.+}}, [%o2]
define i32 @test_atomic_i32(i32* %ptr1, i32* %ptr2, i32* %ptr3) {
entry:
- %0 = load atomic i32, i32* %ptr1 acquire, align 8
- %1 = load atomic i32, i32* %ptr2 acquire, align 8
+ %0 = load atomic i32, i32* %ptr1 acquire, align 4
+ %1 = load atomic i32, i32* %ptr2 acquire, align 4
%2 = add i32 %0, %1
- store atomic i32 %2, i32* %ptr3 release, align 8
+ store atomic i32 %2, i32* %ptr3 release, align 4
ret i32 %2
}
@@ -32,6 +64,90 @@ entry:
ret i64 %2
}
+;; TODO: the "move %icc" and related instructions are totally
+;; redundant here. There's something weird happening in optimization
+;; of the success value of cmpxchg.
+
+; CHECK-LABEL: test_cmpxchg_i8
+; CHECK: and %o1, -4, %o2
+; CHECK: mov 3, %o3
+; CHECK: andn %o3, %o1, %o1
+; CHECK: sll %o1, 3, %o1
+; CHECK: mov 255, %o3
+; CHECK: sll %o3, %o1, %o5
+; CHECK: xor %o5, -1, %o3
+; CHECK: mov 123, %o4
+; CHECK: ld [%o2], %g2
+; CHECK: sll %o4, %o1, %o4
+; CHECK: and %o0, 255, %o0
+; CHECK: sll %o0, %o1, %o0
+; CHECK: andn %g2, %o5, %g2
+; CHECK: sethi 0, %o5
+; CHECK: [[LABEL1:\.L.*]]:
+; CHECK: or %g2, %o4, %g3
+; CHECK: or %g2, %o0, %g4
+; CHECK: cas [%o2], %g4, %g3
+; CHECK: cmp %g3, %g4
+; CHECK: mov %o5, %g4
+; CHECK: move %icc, 1, %g4
+; CHECK: cmp %g4, 0
+; CHECK: bne [[LABEL2:\.L.*]]
+; CHECK: nop
+; CHECK: and %g3, %o3, %g4
+; CHECK: cmp %g2, %g4
+; CHECK: bne [[LABEL1]]
+; CHECK: mov %g4, %g2
+; CHECK: [[LABEL2]]:
+; CHECK: retl
+; CHECK: srl %g3, %o1, %o0
+define i8 @test_cmpxchg_i8(i8 %a, i8* %ptr) {
+entry:
+ %pair = cmpxchg i8* %ptr, i8 %a, i8 123 monotonic monotonic
+ %b = extractvalue { i8, i1 } %pair, 0
+ ret i8 %b
+}
+
+; CHECK-LABEL: test_cmpxchg_i16
+
+; CHECK: and %o1, -4, %o2
+; CHECK: and %o1, 3, %o1
+; CHECK: xor %o1, 2, %o1
+; CHECK: sll %o1, 3, %o1
+; CHECK: sethi 63, %o3
+; CHECK: or %o3, 1023, %o4
+; CHECK: sll %o4, %o1, %o5
+; CHECK: xor %o5, -1, %o3
+; CHECK: and %o0, %o4, %o4
+; CHECK: ld [%o2], %g2
+; CHECK: mov 123, %o0
+; CHECK: sll %o0, %o1, %o0
+; CHECK: sll %o4, %o1, %o4
+; CHECK: andn %g2, %o5, %g2
+; CHECK: sethi 0, %o5
+; CHECK: [[LABEL1:\.L.*]]:
+; CHECK: or %g2, %o0, %g3
+; CHECK: or %g2, %o4, %g4
+; CHECK: cas [%o2], %g4, %g3
+; CHECK: cmp %g3, %g4
+; CHECK: mov %o5, %g4
+; CHECK: move %icc, 1, %g4
+; CHECK: cmp %g4, 0
+; CHECK: bne [[LABEL2:\.L.*]]
+; CHECK: nop
+; CHECK: and %g3, %o3, %g4
+; CHECK: cmp %g2, %g4
+; CHECK: bne [[LABEL1]]
+; CHECK: mov %g4, %g2
+; CHECK: [[LABEL2]]:
+; CHECK: retl
+; CHECK: srl %g3, %o1, %o0
+define i16 @test_cmpxchg_i16(i16 %a, i16* %ptr) {
+entry:
+ %pair = cmpxchg i16* %ptr, i16 %a, i16 123 monotonic monotonic
+ %b = extractvalue { i16, i1 } %pair, 0
+ ret i16 %b
+}
+
; CHECK-LABEL: test_cmpxchg_i32
; CHECK: mov 123, [[R:%[gilo][0-7]]]
; CHECK: cas [%o1], %o0, [[R]]
@@ -54,6 +170,26 @@ entry:
ret i64 %b
}
+; CHECK-LABEL: test_swap_i8
+; CHECK: mov 42, [[R:%[gilo][0-7]]]
+; CHECK: cas
+
+define i8 @test_swap_i8(i8 %a, i8* %ptr) {
+entry:
+ %b = atomicrmw xchg i8* %ptr, i8 42 monotonic
+ ret i8 %b
+}
+
+; CHECK-LABEL: test_swap_i16
+; CHECK: mov 42, [[R:%[gilo][0-7]]]
+; CHECK: cas
+
+define i16 @test_swap_i16(i16 %a, i16* %ptr) {
+entry:
+ %b = atomicrmw xchg i16* %ptr, i16 42 monotonic
+ ret i16 %b
+}
+
; CHECK-LABEL: test_swap_i32
; CHECK: mov 42, [[R:%[gilo][0-7]]]
; CHECK: swap [%o1], [[R]]
@@ -73,12 +209,36 @@ entry:
ret i64 %b
}
-; CHECK-LABEL: test_load_add_32
+; CHECK-LABEL: test_load_sub_i8
+; CHECK: membar
+; CHECK: .L{{.*}}:
+; CHECK: sub
+; CHECK: cas [{{%[gilo][0-7]}}]
+; CHECK: membar
+define zeroext i8 @test_load_sub_i8(i8* %p, i8 zeroext %v) {
+entry:
+ %0 = atomicrmw sub i8* %p, i8 %v seq_cst
+ ret i8 %0
+}
+
+; CHECK-LABEL: test_load_sub_i16
+; CHECK: membar
+; CHECK: .L{{.*}}:
+; CHECK: sub
+; CHECK: cas [{{%[gilo][0-7]}}]
+; CHECK: membar
+define zeroext i16 @test_load_sub_i16(i16* %p, i16 zeroext %v) {
+entry:
+ %0 = atomicrmw sub i16* %p, i16 %v seq_cst
+ ret i16 %0
+}
+
+; CHECK-LABEL: test_load_add_i32
; CHECK: membar
; CHECK: add [[V:%[gilo][0-7]]], %o1, [[U:%[gilo][0-7]]]
; CHECK: cas [%o0], [[V]], [[U]]
; CHECK: membar
-define zeroext i32 @test_load_add_32(i32* %p, i32 zeroext %v) {
+define zeroext i32 @test_load_add_i32(i32* %p, i32 zeroext %v) {
entry:
%0 = atomicrmw add i32* %p, i32 %v seq_cst
ret i32 %0
diff --git a/test/CodeGen/SPARC/float.ll b/test/CodeGen/SPARC/float.ll
index c4cc04420ad7a..248e98549c9f7 100644
--- a/test/CodeGen/SPARC/float.ll
+++ b/test/CodeGen/SPARC/float.ll
@@ -1,11 +1,13 @@
-; RUN: llc -march=sparc < %s | FileCheck %s -check-prefix=V8
+; RUN: llc -march=sparc < %s | FileCheck %s -check-prefix=V8 -check-prefix=V8-BE
+; RUN: llc -march=sparcel < %s | FileCheck %s -check-prefix=V8 -check-prefix=V8-EL
; 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-BE: fnegs %f0, %f0
+; V8-EL: fnegs %f1, %f1
; V8-UNOPT-LABEL: test_neg:
; V8-UNOPT: fnegs
@@ -27,7 +29,8 @@ entry:
}
; V8-LABEL: test_abs:
-; V8: fabss %f0, %f0
+; V8-BE: fabss %f0, %f0
+; V8-EL: fabss %f1, %f1
; V8-UNOPT-LABEL: test_abs:
; V8-UNOPT: fabss
diff --git a/test/CodeGen/SPARC/fp128.ll b/test/CodeGen/SPARC/fp128.ll
index e0eaf93a733ea..bcc013b73575a 100644
--- a/test/CodeGen/SPARC/fp128.ll
+++ b/test/CodeGen/SPARC/fp128.ll
@@ -1,30 +1,24 @@
-; 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
+; RUN: llc < %s -march=sparc -mattr=hard-quad-float | FileCheck %s --check-prefix=CHECK --check-prefix=HARD --check-prefix=BE
+; RUN: llc < %s -march=sparcel -mattr=hard-quad-float | FileCheck %s --check-prefix=CHECK --check-prefix=HARD --check-prefix=EL
+; RUN: llc < %s -march=sparc -mattr=-hard-quad-float | FileCheck %s --check-prefix=CHECK --check-prefix=SOFT --check-prefix=BE
+; RUN: llc < %s -march=sparcel -mattr=-hard-quad-float | FileCheck %s --check-prefix=CHECK --check-prefix=SOFT --check-prefix=EL
-; HARD-LABEL: f128_ops
-; HARD: ldd
-; HARD: ldd
-; HARD: ldd
-; HARD: ldd
+; CHECK-LABEL: f128_ops:
+; CHECK: ldd
+; CHECK: ldd
+; CHECK: ldd
+; CHECK: 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
+; CHECK: std
+; CHECK: std
define void @f128_ops(fp128* noalias sret %scalar.result, fp128* byval %a, fp128* byval %b, fp128* byval %c, fp128* byval %d) {
entry:
@@ -40,19 +34,12 @@ entry:
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 {{%[oi]7}}+12
-
-; SOFT-LABEL: f128_spill
-; SOFT: std %f{{.+}}, [%[[S0:.+]]]
-; SOFT: std %f{{.+}}, [%[[S1:.+]]]
-; SOFT-DAG: ldd [%[[S0]]], %f{{.+}}
-; SOFT-DAG: ldd [%[[S1]]], %f{{.+}}
-; SOFT: jmp {{%[oi]7}}+12
+; CHECK-LABEL: f128_spill:
+; CHECK: std %f{{.+}}, [%[[S0:.+]]]
+; CHECK: std %f{{.+}}, [%[[S1:.+]]]
+; CHECK-DAG: ldd [%[[S0]]], %f{{.+}}
+; CHECK-DAG: ldd [%[[S1]]], %f{{.+}}
+; CHECK: jmp {{%[oi]7}}+12
define void @f128_spill(fp128* noalias sret %scalar.result, fp128* byval %a) {
entry:
@@ -62,11 +49,9 @@ entry:
ret void
}
-; HARD-LABEL: f128_compare
+; CHECK-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) {
@@ -78,11 +63,9 @@ entry:
ret i32 %ret
}
-; HARD-LABEL: f128_compare2
-; HARD: fcmpq
-; HARD: fb{{ule|g}}
-
-; SOFT-LABEL: f128_compare2
+; CHECK-LABEL: f128_compare2:
+; HARD: fcmpq
+; HARD: fb{{ule|g}}
; SOFT: _Q_cmp
; SOFT: cmp
@@ -99,11 +82,11 @@ entry:
}
-; HARD-LABEL: f128_abs
-; HARD: fabss
-
-; SOFT-LABEL: f128_abs
-; SOFT: fabss
+; CHECK-LABEL: f128_abs:
+; CHECK: ldd [%o0], %f0
+; CHECK: ldd [%o0+8], %f2
+; BE: fabss %f0, %f0
+; EL: fabss %f3, %f3
define void @f128_abs(fp128* noalias sret %scalar.result, fp128* byval %a) {
entry:
@@ -115,10 +98,8 @@ entry:
declare fp128 @llvm.fabs.f128(fp128) nounwind readonly
-; HARD-LABEL: int_to_f128
+; CHECK-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) {
@@ -128,17 +109,12 @@ entry:
ret void
}
-; HARD-LABEL: fp128_unaligned
-; HARD: ldub
-; HARD: faddq
-; HARD: stb
-; HARD: ret
-
-; SOFT-LABEL: fp128_unaligned
-; SOFT: ldub
+; CHECK-LABEL: fp128_unaligned:
+; CHECK: ldub
+; HARD: faddq
; SOFT: call _Q_add
-; SOFT: stb
-; SOFT: ret
+; CHECK: stb
+; CHECK: ret
define void @fp128_unaligned(fp128* %a, fp128* %b, fp128* %c) {
entry:
@@ -149,10 +125,8 @@ entry:
ret void
}
-; HARD-LABEL: uint_to_f128
+; CHECK-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) {
@@ -162,11 +136,9 @@ entry:
ret void
}
-; HARD-LABEL: f128_to_i32
+; CHECK-LABEL: f128_to_i32:
; HARD: fqtoi
; HARD: fqtoi
-
-; SOFT-LABEL: f128_to_i32
; SOFT: call _Q_qtou
; SOFT: call _Q_qtoi
@@ -181,13 +153,11 @@ entry:
ret i32 %4
}
-; HARD-LABEL: test_itoq_qtoi
+; CHECK-LABEL: test_itoq_qtoi
; HARD-DAG: call _Q_lltoq
; HARD-DAG: call _Q_qtoll
; HARD-DAG: fitoq
; HARD-DAG: fqtoi
-
-; SOFT-LABEL: test_itoq_qtoi
; SOFT-DAG: call _Q_lltoq
; SOFT-DAG: call _Q_qtoll
; SOFT-DAG: call _Q_itoq
@@ -209,15 +179,11 @@ entry:
ret void
}
-; HARD-LABEL: test_utoq_qtou
-; HARD-DAG: call _Q_ulltoq
-; HARD-DAG: call _Q_qtoull
+; CHECK-LABEL: test_utoq_qtou:
+; CHECK-DAG: call _Q_ulltoq
+; CHECK-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
@@ -237,8 +203,11 @@ entry:
ret void
}
-; SOFT-LABEL: f128_neg
-; SOFT: fnegs
+; CHECK-LABEL: f128_neg:
+; CHECK: ldd [%o0], %f0
+; CHECK: ldd [%o0+8], %f2
+; BE: fnegs %f0, %f0
+; EL: fnegs %f3, %f3
define void @f128_neg(fp128* noalias sret %scalar.result, fp128* byval %a) {
entry:
diff --git a/test/CodeGen/SPARC/func-addr.ll b/test/CodeGen/SPARC/func-addr.ll
new file mode 100644
index 0000000000000..3d1cd9c306908
--- /dev/null
+++ b/test/CodeGen/SPARC/func-addr.ll
@@ -0,0 +1,51 @@
+; 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
+
+define void @func1() #0 {
+entry:
+ ret void
+}
+
+define void @test() #0 {
+entry:
+ %pFunc = alloca void (...)*, align 4
+ store void (...)* bitcast (void ()* @func1 to void (...)*), void (...)** %pFunc, align 4
+ %0 = load void (...)*, void (...)** %pFunc, align 4
+ %callee.knr.cast = bitcast void (...)* %0 to void ()*
+ call void %callee.knr.cast()
+
+; abs32-LABEL: test
+; abs32: sethi %hi(func1), %i0
+; abs32: add %i0, %lo(func1), %i1
+; abs32: call %i0+%lo(func1)
+
+; abs44-LABEL: test
+; abs44: sethi %h44(func1), %i0
+; abs44: add %i0, %m44(func1), %i0
+; abs44: sllx %i0, 12, %i0
+; abs44: add %i0, %l44(func1), %i1
+; abs44: call %i0+%l44(func1)
+
+; abs64-LABEL: test
+; abs64: sethi %hi(func1), %i0
+; abs64: add %i0, %lo(func1), %i0
+; abs64: sethi %hh(func1), %i1
+; abs64: add %i1, %hm(func1), %i1
+
+; v8pic32-LABEL: test
+; v8pic32: sethi %hi(func1), %i1
+; v8pic32: add %i1, %lo(func1), %i1
+; v8pic32: ld [%i0+%i1], %i0
+
+; v9pic32-LABEL: test
+; v9pic32: sethi %hi(func1), %i1
+; v9pic32: add %i1, %lo(func1), %i1
+; v9pic32: ldx [%i0+%i1], %i0
+; v9pic32: call %i0
+
+ ret void
+}
diff --git a/test/CodeGen/SPARC/inlineasm.ll b/test/CodeGen/SPARC/inlineasm.ll
index d54c5c6bc7801..af631f0d29f54 100644
--- a/test/CodeGen/SPARC/inlineasm.ll
+++ b/test/CodeGen/SPARC/inlineasm.ll
@@ -8,6 +8,18 @@ entry:
ret i32 %0
}
+;; Check tests only that the constraints are accepted without a compiler failure.
+; CHECK-LABEL: test_constraints_nro:
+%struct.anon = type { i32, i32 }
+@v = external global %struct.anon, align 4
+define void @test_constraints_nro() {
+entry:
+ %0 = load i32, i32* getelementptr inbounds (%struct.anon, %struct.anon* @v, i32 0, i32 0);
+ %1 = load i32, i32* getelementptr inbounds (%struct.anon, %struct.anon* @v, i32 0, i32 1);
+ tail call void asm sideeffect "", "nro,nro"(i32 %0, i32 %1)
+ ret void
+}
+
; CHECK-LABEL: test_constraint_I:
; CHECK: add %o0, 1023, %o0
define i32 @test_constraint_I(i32 %a) {
diff --git a/test/CodeGen/SPARC/missinglabel.ll b/test/CodeGen/SPARC/missinglabel.ll
index bcf384b7ad290..3626feee4c387 100644
--- a/test/CodeGen/SPARC/missinglabel.ll
+++ b/test/CodeGen/SPARC/missinglabel.ll
@@ -4,14 +4,14 @@ target triple = "sparc64-unknown-linux-gnu"
define void @f() align 2 {
entry:
-; CHECK: %xcc, .LBB0_1
+; CHECK: %xcc, .LBB0_2
%cmp = icmp eq i64 undef, 0
br i1 %cmp, label %targetblock, label %cond.false
cond.false:
unreachable
-; CHECK: .LBB0_1: ! %targetblock
+; CHECK: .LBB0_2: ! %targetblock
targetblock:
br i1 undef, label %cond.false.i83, label %exit.i85
diff --git a/test/CodeGen/SPARC/sjlj.ll b/test/CodeGen/SPARC/sjlj.ll
new file mode 100755
index 0000000000000..3bf583aa47543
--- /dev/null
+++ b/test/CodeGen/SPARC/sjlj.ll
@@ -0,0 +1,88 @@
+; RUN: llc < %s -march=sparc | FileCheck %s
+; RUN: llc < %s -march=sparc -mcpu=leon2 | FileCheck %s
+; RUN: llc < %s -march=sparc -mcpu=leon3 | FileCheck %s
+; RUN: llc < %s -march=sparc -mcpu=leon4 | FileCheck %s
+
+%struct.__jmp_buf_tag = type { [64 x i64], i32, %struct.__sigset_t, [8 x i8] }
+%struct.__sigset_t = type { [16 x i64] }
+
+@env_sigill = internal global [1 x %struct.__jmp_buf_tag] zeroinitializer, align 16
+
+define void @foo() #0 {
+entry:
+ call void @llvm.eh.sjlj.longjmp(i8* bitcast ([1 x %struct.__jmp_buf_tag]* @env_sigill to i8*))
+ unreachable
+
+; CHECK: @foo
+; CHECK: ta 3
+; CHECK: ld [%i0], %fp
+; CHECK: ld [%i0+4], %i1
+; CHECK: ld [%i0+8], %sp
+; CHECK: jmp %i1
+; CHECK: ld [%i0+12], %i7
+
+return: ; No predecessors!
+ ret void
+}
+
+declare void @llvm.eh.sjlj.longjmp(i8*) #1
+
+define signext i32 @main() #0 {
+entry:
+ %retval = alloca i32, align 4
+ store i32 0, i32* %retval
+ %0 = call i8* @llvm.frameaddress(i32 0)
+ store i8* %0, i8** bitcast ([1 x %struct.__jmp_buf_tag]* @env_sigill to i8**)
+ %1 = call i8* @llvm.stacksave()
+ store i8* %1, i8** getelementptr (i8*, i8** bitcast ([1 x %struct.__jmp_buf_tag]* @env_sigill to i8**), i32 2)
+ %2 = call i32 @llvm.eh.sjlj.setjmp(i8* bitcast ([1 x %struct.__jmp_buf_tag]* @env_sigill to i8*))
+ %tobool = icmp ne i32 %2, 0
+ br i1 %tobool, label %if.then, label %if.else
+
+if.then: ; preds = %entry
+ store i32 1, i32* %retval
+ br label %return
+
+if.else: ; preds = %entry
+ call void @foo()
+ br label %if.end
+
+if.end: ; preds = %if.else
+ store i32 0, i32* %retval
+ br label %return
+
+return: ; preds = %if.end, %if.then
+ %3 = load i32, i32* %retval
+ ret i32 %3
+
+; CHECK: @main
+; CHECK: st %fp, [%i0]
+; CHECK: sethi %hi(.LBB1_2), %i1
+; CHECK: or %i1, %lo(.LBB1_2), %i1
+; CHECK: st %i1, [%i0+4]
+; CHECK: st %sp, [%i0+8]
+; CHECK: bn .LBB1_2
+; CHECK: st %i7, [%i0+12]
+; CHECK: ba .LBB1_1
+; CHECK: nop
+; CHECK:.LBB1_1: ! %entry
+; CHECK: ba .LBB1_3
+; CHECK: mov %g0, %i0
+; CHECK:.LBB1_2: ! Block address taken
+; CHECK: mov 1, %i0
+; CHECK:.LBB1_3: ! %entry
+; CHECK: cmp %i0, 0
+; CHECK: be .LBB1_5
+; CHECK: nop
+}
+declare i8* @llvm.frameaddress(i32) #2
+
+declare i8* @llvm.stacksave() #3
+
+declare i32 @llvm.eh.sjlj.setjmp(i8*) #3
+
+attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { noreturn nounwind }
+attributes #2 = { nounwind readnone }
+attributes #3 = { nounwind }
+
diff --git a/test/CodeGen/SPARC/soft-float.ll b/test/CodeGen/SPARC/soft-float.ll
new file mode 100644
index 0000000000000..53ca1974659e9
--- /dev/null
+++ b/test/CodeGen/SPARC/soft-float.ll
@@ -0,0 +1,235 @@
+; RUN: llc -march=sparc -mattr=soft-float -O0 < %s | FileCheck %s
+
+; Arithmetic functions
+
+define float @test_addsf3(float %a, float %b) #0 {
+ ; CHECK-LABEL: test_addsf3:
+ ; CHECK: call __addsf3
+ %add = fadd float %a, %b
+ ret float %add
+}
+
+define double @test_adddf3(double %a, double %b) #0 {
+ ; CHECK-LABEL: test_adddf3:
+ ; CHECK: call __adddf3
+ %add = fadd double %a, %b
+ ret double %add
+}
+
+define fp128 @test_addtf3(fp128 %a, fp128 %b) #0 {
+ ; CHECK-LABEL: test_addtf3:
+ ; CHECK: call __addtf3
+ %add = fadd fp128 %a, %b
+ ret fp128 %add
+}
+
+define float @test_mulsf3(float %a, float %b) #0 {
+ ; CHECK-LABEL: test_mulsf3:
+ ; CHECK: call __mulsf3
+ %mul = fmul float %a, %b
+ ret float %mul
+}
+
+define double @test_muldf3(double %a, double %b) #0 {
+ ; CHECK-LABEL: test_muldf3:
+ ; CHECK: call __muldf3
+ %mul = fmul double %a, %b
+ ret double %mul
+}
+
+define fp128 @test_multf3(fp128 %a, fp128 %b) #0 {
+ ; CHECK-LABEL: test_multf3:
+ ; CHECK: call __multf3
+ %mul = fmul fp128 %a, %b
+ ret fp128 %mul
+}
+
+define float @test_subsf3(float %a, float %b) #0 {
+ ; CHCEK-LABEL: test_subsf3:
+ ; CHECK: call __subsf3
+ %sub = fsub float %a, %b
+ ret float %sub
+}
+
+define double @test_subdf3(double %a, double %b) #0 {
+ ; CHCEK-LABEL: test_subdf3:
+ ; CHECK: call __subdf3
+ %sub = fsub double %a, %b
+ ret double %sub
+}
+
+define fp128 @test_subtf3(fp128 %a, fp128 %b) #0 {
+ ; CHCEK-LABEL: test_subtf3:
+ ; CHECK: call __subtf3
+ %sub = fsub fp128 %a, %b
+ ret fp128 %sub
+}
+
+define float @test_divsf3(float %a, float %b) #0 {
+ ; CHECK-LABEL: test_divsf3:
+ ; CHECK: call __divsf3
+ %div = fdiv float %a, %b
+ ret float %div
+}
+
+define double @test_divdf3(double %a, double %b) #0 {
+ ; CHECK-LABEL: test_divdf3:
+ ; CHECK: call __divdf3
+ %div = fdiv double %a, %b
+ ret double %div
+}
+
+define fp128 @test_divtf3(fp128 %a, fp128 %b) #0 {
+ ; CHECK-LABEL: test_divtf3:
+ ; CHECK: call __divtf3
+ %div = fdiv fp128 %a, %b
+ ret fp128 %div
+}
+
+; Comparison functions
+define i1 @test_unordsf2(float %a, float %b) #0 {
+ ; CHECK-LABEL: test_unordsf2:
+ ; CHECK: call __unordsf2
+ %cmp = fcmp uno float %a, %b
+ ret i1 %cmp
+}
+
+define i1 @test_unorddf2(double %a, double %b) #0 {
+ ; CHECK-LABEL: test_unorddf2:
+ ; CHECK: call __unorddf2
+ %cmp = fcmp uno double %a, %b
+ ret i1 %cmp
+}
+
+define i1 @test_unordtf2(fp128 %a, fp128 %b) #0 {
+ ; CHECK-LABEL: test_unordtf2:
+ ; CHECK: call __unordtf2
+ %cmp = fcmp uno fp128 %a, %b
+ ret i1 %cmp
+}
+
+define i1 @test_eqsf2(float %a, float %b) #0 {
+ ; CHECK-LABEL: test_eqsf2:
+ ; CHECK: call __eqsf2
+ %cmp = fcmp oeq float %a, %b
+ ret i1 %cmp
+}
+
+define i1 @test_eqdf2(double %a, double %b) #0 {
+ ; CHECK-LABEL: test_eqdf2:
+ ; CHECK: call __eqdf2
+ %cmp = fcmp oeq double %a, %b
+ ret i1 %cmp
+}
+
+define i1 @test_eqtf2(fp128 %a, fp128 %b) #0 {
+ ; CHECK-LABEL: test_eqtf2:
+ ; CHECK: call __eqtf2
+ %cmp = fcmp oeq fp128 %a, %b
+ ret i1 %cmp
+}
+
+define i1 @test_nesf2(float %a, float %b) #0 {
+ ; CHECK-LABEL: test_nesf2:
+ ; CHECK: call __nesf2
+ %cmp = fcmp une float %a, %b
+ ret i1 %cmp
+}
+
+define i1 @test_nedf2(double %a, double %b) #0 {
+ ; CHECK-LABEL: test_nedf2:
+ ; CHECK: call __nedf2
+ %cmp = fcmp une double %a, %b
+ ret i1 %cmp
+}
+
+define i1 @test_netf2(fp128 %a, fp128 %b) #0 {
+ ; CHECK-LABEL: test_netf2:
+ ; CHECK: call __netf2
+ %cmp = fcmp une fp128 %a, %b
+ ret i1 %cmp
+}
+
+define i1 @test_gesf2(float %a, float %b) #0 {
+ ; CHECK-LABLE: test_gesf2:
+ ; CHECK: call __gesf2
+ %cmp = fcmp oge float %a, %b
+ ret i1 %cmp
+}
+
+define i1 @test_gedf2(double %a, double %b) #0 {
+ ; CHECK-LABLE: test_gedf2:
+ ; CHECK: call __gedf2
+ %cmp = fcmp oge double %a, %b
+ ret i1 %cmp
+}
+
+define i1 @test_getf2(fp128 %a, fp128 %b) #0 {
+ ; CHECK-LABLE: test_getf2:
+ ; CHECK: call __getf2
+ %cmp = fcmp oge fp128 %a, %b
+ ret i1 %cmp
+}
+
+define i1 @test_ltsf2(float %a, float %b) #0 {
+ ; CHECK-LABEL: test_ltsf2:
+ ; CHECK: call __ltsf2
+ %cmp = fcmp olt float %a, %b
+ ret i1 %cmp
+}
+
+define i1 @test_ltdf2(double %a, double %b) #0 {
+ ; CHECK-LABEL: test_ltdf2:
+ ; CHECK: call __ltdf2
+ %cmp = fcmp olt double %a, %b
+ ret i1 %cmp
+}
+
+define i1 @test_lttf2(fp128 %a, fp128 %b) #0 {
+ ; CHECK-LABEL: test_lttf2:
+ ; CHECK: call __lttf2
+ %cmp = fcmp olt fp128 %a, %b
+ ret i1 %cmp
+}
+
+define i1 @test_lesf2(float %a, float %b) #0 {
+ ; CHECK-LABEL: test_lesf2:
+ ; CHECK: call __lesf2
+ %cmp = fcmp ole float %a, %b
+ ret i1 %cmp
+}
+
+define i1 @test_ledf2(double %a, double %b) #0 {
+ ; CHECK-LABEL: test_ledf2:
+ ; CHECK: call __ledf2
+ %cmp = fcmp ole double %a, %b
+ ret i1 %cmp
+}
+
+define i1 @test_letf2(fp128 %a, fp128 %b) #0 {
+ ; CHECK-LABEL: test_letf2:
+ ; CHECK: call __letf2
+ %cmp = fcmp ole fp128 %a, %b
+ ret i1 %cmp
+}
+
+define i1 @test_gtsf2(float %a, float %b) #0 {
+ ; CHECK-LABEL: test_gtsf2:
+ ; CHECK: call __gtsf2
+ %cmp = fcmp ogt float %a, %b
+ ret i1 %cmp
+}
+
+define i1 @test_gtdf2(double %a, double %b) #0 {
+ ; CHECK-LABEL: test_gtdf2:
+ ; CHECK: call __gtdf2
+ %cmp = fcmp ogt double %a, %b
+ ret i1 %cmp
+}
+
+define i1 @test_gttf2(fp128 %a, fp128 %b) #0 {
+ ; CHECK-LABEL: test_gttf2:
+ ; CHECK: call __gttf2
+ %cmp = fcmp ogt fp128 %a, %b
+ ret i1 %cmp
+}
diff --git a/test/CodeGen/SPARC/stack-protector.ll b/test/CodeGen/SPARC/stack-protector.ll
new file mode 100644
index 0000000000000..70a73664aa16a
--- /dev/null
+++ b/test/CodeGen/SPARC/stack-protector.ll
@@ -0,0 +1,33 @@
+; RUN: llc -mtriple=sparc-unknown-linux < %s | FileCheck %s --check-prefix=LINUX-32
+; RUN: llc -mtriple=sparc64-unknown-linux < %s | FileCheck %s --check-prefix=LINUX-64
+; RUN: llc -mtriple=sparc-unknown-solaris < %s | FileCheck %s --check-prefix=GENERIC
+; RUN: llc -mtriple=sparc64-unknown-solaris < %s | FileCheck %s --check-prefix=GENERIC
+
+; LINUX-32: ld [%g7+20], [[REG1:%[ilo][0-9]*]]
+; LINUX-64: ldx [%g7+40], [[REG1:%[ilo][0-9]*]]
+; LINUX-32-NOT: __stack_chk_guard
+; LINUX-64-NOT: __stack_chk_guard
+; GENERIC: __stack_chk_guard
+
+@"\01LC" = internal constant [11 x i8] c"buf == %s\0A\00" ; <[11 x i8]*> [#uses=1]
+
+define void @test(i8* %a) nounwind ssp {
+entry:
+ %a_addr = alloca i8* ; <i8**> [#uses=2]
+ %buf = alloca [8 x i8] ; <[8 x i8]*> [#uses=2]
+ %"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
+ store i8* %a, i8** %a_addr
+ %buf1 = bitcast [8 x i8]* %buf to i8* ; <i8*> [#uses=1]
+ %0 = load i8*, i8** %a_addr, align 4 ; <i8*> [#uses=1]
+ %1 = call i8* @strcpy(i8* %buf1, i8* %0) nounwind ; <i8*> [#uses=0]
+ %buf2 = bitcast [8 x i8]* %buf to i8* ; <i8*> [#uses=1]
+ %2 = call i32 (i8*, ...) @printf(i8* getelementptr ([11 x i8], [11 x i8]* @"\01LC", i32 0, i32 0), i8* %buf2) nounwind ; <i32> [#uses=0]
+ br label %return
+
+return: ; preds = %entry
+ ret void
+}
+
+declare i8* @strcpy(i8*, i8*) nounwind
+
+declare i32 @printf(i8*, ...) nounwind
diff --git a/test/CodeGen/SPARC/thread-pointer.ll b/test/CodeGen/SPARC/thread-pointer.ll
new file mode 100644
index 0000000000000..33e99aa94747e
--- /dev/null
+++ b/test/CodeGen/SPARC/thread-pointer.ll
@@ -0,0 +1,11 @@
+; RUN: llc < %s -mtriple=sparc-unknown-linux-gnu | FileCheck %s
+; RUN: llc < %s -mtriple=sparc64-unknown-linux-gnu | FileCheck %s
+
+; Function Attrs: nounwind readnone
+declare i8* @llvm.thread.pointer() #1
+
+define i8* @thread_pointer() {
+; CHECK: mov %g7, %o0
+ %1 = tail call i8* @llvm.thread.pointer()
+ ret i8* %1
+}
diff --git a/test/CodeGen/SPARC/vector-call.ll b/test/CodeGen/SPARC/vector-call.ll
new file mode 100644
index 0000000000000..3b004b6230f8c
--- /dev/null
+++ b/test/CodeGen/SPARC/vector-call.ll
@@ -0,0 +1,33 @@
+; RUN: llc < %s -march=sparc | FileCheck %s
+
+; Verify that we correctly handle vector types that appear directly
+; during call lowering. These may cause issue as v2i32 is a legal type
+; for the implementation of LDD
+
+; CHECK-LABEL: fun16v:
+; CHECK: foo1_16v
+; CHECK: foo2_16v
+
+define <2 x i16> @fun16v() #0 {
+ %1 = tail call <2 x i16> @foo1_16v()
+ %2 = tail call <2 x i16> @foo2_16v()
+ %3 = and <2 x i16> %2, %1
+ ret <2 x i16> %3
+}
+
+declare <2 x i16> @foo1_16v() #0
+declare <2 x i16> @foo2_16v() #0
+
+; CHECK-LABEL: fun32v:
+; CHECK: foo1_32v
+; CHECK: foo2_32v
+
+define <2 x i32> @fun32v() #0 {
+ %1 = tail call <2 x i32> @foo1_32v()
+ %2 = tail call <2 x i32> @foo2_32v()
+ %3 = and <2 x i32> %2, %1
+ ret <2 x i32> %3
+}
+
+declare <2 x i32> @foo1_32v() #0
+declare <2 x i32> @foo2_32v() #0
diff --git a/test/CodeGen/SPARC/zerostructcall.ll b/test/CodeGen/SPARC/zerostructcall.ll
new file mode 100644
index 0000000000000..0a8ff65e1585f
--- /dev/null
+++ b/test/CodeGen/SPARC/zerostructcall.ll
@@ -0,0 +1,51 @@
+; RUN: llc < %s -march=sparc | FileCheck %s
+
+; CHECK-LABEL: struct_ptr_test
+; CHECK: call struct_ptr_fn
+; CHECK-NEXT: st %i0, [%fp+-4]
+; CHECK-NEXT: ret
+
+%struct.S = type {}
+
+define void @struct_ptr_test(i32 %i) {
+entry:
+ %i.addr = alloca i32, align 4
+ store i32 %i, i32* %i.addr, align 4
+ %0 = bitcast i32* %i.addr to %struct.S*
+ call void @struct_ptr_fn(%struct.S* byval align 1 %0)
+ ret void
+}
+
+declare void @struct_ptr_fn(%struct.S* byval align 1)
+
+; CHECK-LABEL: struct_test
+; CHECK: call struct_fn
+; CHECK-NEXT: nop
+; CHECK-NEXT: ret
+
+%struct.U = type {}
+
+@a = internal global [1 x %struct.U] zeroinitializer, align 1
+
+define void @struct_test() {
+entry:
+ tail call void @struct_fn(%struct.U* byval align 1 getelementptr inbounds ([1 x %struct.U], [1 x %struct.U]* @a, i32 0, i32 0))
+ ret void
+}
+
+; CHECK-LABEL: struct_arg_test
+; CHECK: call struct_arg_fn
+; CHECK-NEXT: nop
+; CHECK-NEXT: ret
+
+declare void @struct_fn(%struct.U* byval align 1)
+
+@b = internal global [1 x %struct.U] zeroinitializer, align 1
+
+define void @struct_arg_test() {
+entry:
+ tail call void @struct_arg_fn(%struct.U* byval align 1 getelementptr inbounds ([1 x %struct.U], [1 x %struct.U]* @b, i32 0, i32 0))
+ ret void
+}
+
+declare void @struct_arg_fn(%struct.U* byval align 1)