diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2013-12-22 00:04:03 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2013-12-22 00:04:03 +0000 |
| commit | f8af5cf600354830d4ccf59732403f0f073eccb9 (patch) | |
| tree | 2ba0398b4c42ad4f55561327538044fd2c925a8b /test/CodeGen/SPARC | |
| parent | 59d6cff90eecf31cb3dd860c4e786674cfdd42eb (diff) | |
Notes
Diffstat (limited to 'test/CodeGen/SPARC')
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" |
