mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-13 20:32:21 +00:00
[mips] Add tests for the 'ret', 'call', and 'indirectbr' LLVM IR instruction.
Summary: The tests in this directory are intended to test a single IR instruction with as few dependencies on other instructions as possible. The aim is to be very confident that each LLVM-IR instruction is implemented correctly and with the optimal sequence of instructions, as well as to make it easy to tell what is tested, and make it easier to bring up new ISA revisions in the future. This gives us a good foundation on which to test bigger things. These particular tests will allow testing that MIPS32r6/MIPS64r6 generate the correct return instruction for returns, calls, and indirect branches. This will be a bit tricky since the assembly text is identical but the instruction is actually different. On MIPS32r6/MIPS64r6 'jr $rs' has been removed in favour of the equivalent 'jalr $zero, $rs'. 'jr $rs' remains as an alias for 'jalr $zero, $rs'. Differential Revision: http://reviews.llvm.org/D4266 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@212345 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
ada0f6a93e
commit
8ce13cfc08
160
test/CodeGen/Mips/llvm-ir/call.ll
Normal file
160
test/CodeGen/Mips/llvm-ir/call.ll
Normal file
@ -0,0 +1,160 @@
|
||||
; Test the 'call' instruction and the tailcall variant.
|
||||
|
||||
; FIXME: We should remove the need for -enable-mips-tail-calls
|
||||
; RUN: llc -march=mips -mcpu=mips32 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32
|
||||
; RUN: llc -march=mips -mcpu=mips32r2 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=O32
|
||||
; RUN: llc -march=mips64 -mcpu=mips4 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64
|
||||
; RUN: llc -march=mips64 -mcpu=mips64 -enable-mips-tail-calls < %s | FileCheck %s -check-prefix=ALL -check-prefix=N64
|
||||
|
||||
declare void @extern_void_void()
|
||||
declare i32 @extern_i32_void()
|
||||
declare float @extern_float_void()
|
||||
|
||||
define i32 @call_void_void() {
|
||||
; ALL-LABEL: call_void_void:
|
||||
|
||||
; O32: lw $[[TGT:[0-9]+]], %call16(extern_void_void)($gp)
|
||||
|
||||
; N64: ld $[[TGT:[0-9]+]], %call16(extern_void_void)($gp)
|
||||
|
||||
; ALL: jalr $[[TGT]]
|
||||
|
||||
call void @extern_void_void()
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i32 @call_i32_void() {
|
||||
; ALL-LABEL: call_i32_void:
|
||||
|
||||
; O32: lw $[[TGT:[0-9]+]], %call16(extern_i32_void)($gp)
|
||||
|
||||
; N64: ld $[[TGT:[0-9]+]], %call16(extern_i32_void)($gp)
|
||||
|
||||
; ALL: jalr $[[TGT]]
|
||||
|
||||
%1 = call i32 @extern_i32_void()
|
||||
%2 = add i32 %1, 1
|
||||
ret i32 %2
|
||||
}
|
||||
|
||||
define float @call_float_void() {
|
||||
; ALL-LABEL: call_float_void:
|
||||
|
||||
; FIXME: Not sure why we don't use $gp directly on such a simple test. We should
|
||||
; look into it at some point.
|
||||
; O32: addu $[[GP:[0-9]+]], ${{[0-9]+}}, $25
|
||||
; O32: lw $[[TGT:[0-9]+]], %call16(extern_float_void)($[[GP]])
|
||||
|
||||
; N64: ld $[[TGT:[0-9]+]], %call16(extern_float_void)($gp)
|
||||
|
||||
; ALL: jalr $[[TGT]]
|
||||
|
||||
; O32: move $gp, $[[GP]]
|
||||
|
||||
%1 = call float @extern_float_void()
|
||||
%2 = fadd float %1, 1.0
|
||||
ret float %2
|
||||
}
|
||||
|
||||
define void @musttail_call_void_void() {
|
||||
; ALL-LABEL: musttail_call_void_void:
|
||||
|
||||
; O32: lw $[[TGT:[0-9]+]], %call16(extern_void_void)($gp)
|
||||
|
||||
; N64: ld $[[TGT:[0-9]+]], %call16(extern_void_void)($gp)
|
||||
|
||||
; ALL: jr $[[TGT]]
|
||||
|
||||
musttail call void @extern_void_void()
|
||||
ret void
|
||||
}
|
||||
|
||||
define i32 @musttail_call_i32_void() {
|
||||
; ALL-LABEL: musttail_call_i32_void:
|
||||
|
||||
; O32: lw $[[TGT:[0-9]+]], %call16(extern_i32_void)($gp)
|
||||
|
||||
; N64: ld $[[TGT:[0-9]+]], %call16(extern_i32_void)($gp)
|
||||
|
||||
; ALL: jr $[[TGT]]
|
||||
|
||||
%1 = musttail call i32 @extern_i32_void()
|
||||
ret i32 %1
|
||||
}
|
||||
|
||||
define float @musttail_call_float_void() {
|
||||
; ALL-LABEL: musttail_call_float_void:
|
||||
|
||||
; O32: lw $[[TGT:[0-9]+]], %call16(extern_float_void)($gp)
|
||||
|
||||
; N64: ld $[[TGT:[0-9]+]], %call16(extern_float_void)($gp)
|
||||
|
||||
; ALL: jr $[[TGT]]
|
||||
|
||||
%1 = musttail call float @extern_float_void()
|
||||
ret float %1
|
||||
}
|
||||
|
||||
define i32 @indirect_call_void_void(void ()* %addr) {
|
||||
; ALL-LABEL: indirect_call_void_void:
|
||||
|
||||
; ALL: move $25, $4
|
||||
; ALL: jalr $25
|
||||
|
||||
call void %addr()
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i32 @indirect_call_i32_void(i32 ()* %addr) {
|
||||
; ALL-LABEL: indirect_call_i32_void:
|
||||
|
||||
; ALL: move $25, $4
|
||||
; ALL: jalr $25
|
||||
|
||||
%1 = call i32 %addr()
|
||||
%2 = add i32 %1, 1
|
||||
ret i32 %2
|
||||
}
|
||||
|
||||
define float @indirect_call_float_void(float ()* %addr) {
|
||||
; ALL-LABEL: indirect_call_float_void:
|
||||
|
||||
; ALL: move $25, $4
|
||||
; ALL: jalr $25
|
||||
|
||||
%1 = call float %addr()
|
||||
%2 = fadd float %1, 1.0
|
||||
ret float %2
|
||||
}
|
||||
|
||||
; We can't use 'musttail' here because the verifier is too conservative and
|
||||
; prohibits any prototype difference.
|
||||
define void @tail_indirect_call_void_void(void ()* %addr) {
|
||||
; ALL-LABEL: tail_indirect_call_void_void:
|
||||
|
||||
; ALL: move $25, $4
|
||||
; ALL: jr $25
|
||||
|
||||
tail call void %addr()
|
||||
ret void
|
||||
}
|
||||
|
||||
define i32 @tail_indirect_call_i32_void(i32 ()* %addr) {
|
||||
; ALL-LABEL: tail_indirect_call_i32_void:
|
||||
|
||||
; ALL: move $25, $4
|
||||
; ALL: jr $25
|
||||
|
||||
%1 = tail call i32 %addr()
|
||||
ret i32 %1
|
||||
}
|
||||
|
||||
define float @tail_indirect_call_float_void(float ()* %addr) {
|
||||
; ALL-LABEL: tail_indirect_call_float_void:
|
||||
|
||||
; ALL: move $25, $4
|
||||
; ALL: jr $25
|
||||
|
||||
%1 = tail call float %addr()
|
||||
ret float %1
|
||||
}
|
27
test/CodeGen/Mips/llvm-ir/indirectbr.ll
Normal file
27
test/CodeGen/Mips/llvm-ir/indirectbr.ll
Normal file
@ -0,0 +1,27 @@
|
||||
; Test all important variants of the unconditional 'br' instruction.
|
||||
|
||||
; RUN: llc -march=mips -mcpu=mips32 < %s | FileCheck %s -check-prefix=ALL
|
||||
; RUN: llc -march=mips -mcpu=mips32r2 < %s | FileCheck %s -check-prefix=ALL
|
||||
; RUN: llc -march=mips64 -mcpu=mips4 < %s | FileCheck %s -check-prefix=ALL
|
||||
; RUN: llc -march=mips64 -mcpu=mips64 < %s | FileCheck %s -check-prefix=ALL
|
||||
; RUN: llc -march=mips64 -mcpu=mips64r2 < %s | FileCheck %s -check-prefix=ALL
|
||||
|
||||
define i32 @br(i8 *%addr) {
|
||||
; ALL-LABEL: br:
|
||||
; ALL: jr $4
|
||||
; ALL: $BB0_1: # %L1
|
||||
; ALL: jr $ra
|
||||
; ALL: addiu $2, $zero, 0
|
||||
; ALL: $BB0_2: # %L2
|
||||
; ALL: jr $ra
|
||||
; ALL: addiu $2, $zero, 1
|
||||
|
||||
entry:
|
||||
indirectbr i8* %addr, [label %L1, label %L2]
|
||||
|
||||
L1:
|
||||
ret i32 0
|
||||
|
||||
L2:
|
||||
ret i32 1
|
||||
}
|
166
test/CodeGen/Mips/llvm-ir/ret.ll
Normal file
166
test/CodeGen/Mips/llvm-ir/ret.ll
Normal file
@ -0,0 +1,166 @@
|
||||
; Test all important variants of the 'ret' instruction.
|
||||
;
|
||||
; For non-void returns it is necessary to have something to return so we also
|
||||
; test constant generation here.
|
||||
;
|
||||
; We'll test pointer returns in a separate file since the relocation model
|
||||
; affects it.
|
||||
|
||||
; RUN: llc -march=mips -mcpu=mips32 < %s | FileCheck %s -check-prefix=ALL -check-prefix=GPR32 -check-prefix=NO-MTHC1
|
||||
; RUN: llc -march=mips -mcpu=mips32r2 < %s | FileCheck %s -check-prefix=ALL -check-prefix=GPR32 -check-prefix=MTHC1
|
||||
; RUN: llc -march=mips64 -mcpu=mips4 < %s | FileCheck %s -check-prefix=ALL -check-prefix=GPR64 -check-prefix=DMTC1
|
||||
; RUN: llc -march=mips64 -mcpu=mips64 < %s | FileCheck %s -check-prefix=ALL -check-prefix=GPR64 -check-prefix=DMTC1
|
||||
; RUN: llc -march=mips64 -mcpu=mips64r2 < %s | FileCheck %s -check-prefix=ALL -check-prefix=GPR64 -check-prefix=DMTC1
|
||||
|
||||
define void @ret_void() {
|
||||
; ALL-LABEL: ret_void:
|
||||
; ALL: jr $ra
|
||||
ret void
|
||||
}
|
||||
|
||||
define i8 @ret_i8() {
|
||||
; ALL-LABEL: ret_i8:
|
||||
; ALL-DAG: jr $ra
|
||||
; ALL-DAG: addiu $2, $zero, 3
|
||||
ret i8 3
|
||||
}
|
||||
|
||||
define i16 @ret_i16_3() {
|
||||
; ALL-LABEL: ret_i16_3:
|
||||
; ALL-DAG: jr $ra
|
||||
; ALL-DAG: addiu $2, $zero, 3
|
||||
ret i16 3
|
||||
}
|
||||
|
||||
define i16 @ret_i16_256() {
|
||||
; ALL-LABEL: ret_i16_256:
|
||||
; ALL-DAG: jr $ra
|
||||
; ALL-DAG: addiu $2, $zero, 256
|
||||
ret i16 256
|
||||
}
|
||||
|
||||
define i16 @ret_i16_257() {
|
||||
; ALL-LABEL: ret_i16_257:
|
||||
; ALL-DAG: jr $ra
|
||||
; ALL-DAG: addiu $2, $zero, 257
|
||||
ret i16 257
|
||||
}
|
||||
|
||||
define i32 @ret_i32_257() {
|
||||
; ALL-LABEL: ret_i32_257:
|
||||
; ALL-DAG: jr $ra
|
||||
; ALL-DAG: addiu $2, $zero, 257
|
||||
ret i32 257
|
||||
}
|
||||
|
||||
define i32 @ret_i32_65536() {
|
||||
; ALL-LABEL: ret_i32_65536:
|
||||
; ALL-DAG: jr $ra
|
||||
; ALL-DAG: lui $2, 1
|
||||
ret i32 65536
|
||||
}
|
||||
|
||||
define i32 @ret_i32_65537() {
|
||||
; ALL-LABEL: ret_i32_65537:
|
||||
; ALL: lui $[[T0:[0-9]+]], 1
|
||||
; ALL-DAG: jr $ra
|
||||
; ALL-DAG: ori $2, $[[T0]], 1
|
||||
ret i32 65537
|
||||
}
|
||||
|
||||
define i64 @ret_i64_65537() {
|
||||
; ALL-LABEL: ret_i64_65537:
|
||||
; ALL: lui $[[T0:[0-9]+]], 1
|
||||
|
||||
; GPR32-DAG: ori $3, $[[T0]], 1
|
||||
; GPR32-DAG: addiu $2, $zero, 0
|
||||
|
||||
; GPR64-DAG: daddiu $2, $[[T0]], 1
|
||||
|
||||
; ALL-DAG: jr $ra
|
||||
ret i64 65537
|
||||
}
|
||||
|
||||
define i64 @ret_i64_281479271677952() {
|
||||
; ALL-LABEL: ret_i64_281479271677952:
|
||||
; ALL-DAG: lui $[[T0:[0-9]+]], 1
|
||||
|
||||
; GPR32-DAG: ori $2, $[[T0]], 1
|
||||
; GPR32-DAG: addiu $3, $zero, 0
|
||||
|
||||
; GPR64-DAG: daddiu $[[T1:[0-9]+]], $[[T0]], 1
|
||||
; GPR64-DAG: dsll $2, $[[T1]], 32
|
||||
|
||||
; ALL-DAG: jr $ra
|
||||
ret i64 281479271677952
|
||||
}
|
||||
|
||||
define i64 @ret_i64_281479271809026() {
|
||||
; ALL-LABEL: ret_i64_281479271809026:
|
||||
; GPR32-DAG: lui $[[T0:[0-9]+]], 1
|
||||
; GPR32-DAG: lui $[[T1:[0-9]+]], 2
|
||||
; GPR32-DAG: ori $2, $[[T0]], 1
|
||||
; GPR32-DAG: ori $3, $[[T1]], 2
|
||||
|
||||
; GPR64-DAG: ori $[[T0:[0-9]+]], $zero, 32769
|
||||
; GPR64-DAG: dsll $[[T1:[0-9]+]], $[[T0]], 16
|
||||
; GPR64-DAG: daddiu $[[T0:[0-9]+]], $[[T0]], -32767
|
||||
; GPR64-DAG: dsll $[[T1:[0-9]+]], $[[T0]], 17
|
||||
; GPR64-DAG: daddiu $2, $[[T1]], 2
|
||||
|
||||
; ALL-DAG: jr $ra
|
||||
ret i64 281479271809026
|
||||
}
|
||||
|
||||
; TODO: f32
|
||||
define float @ret_float_0x0() {
|
||||
; ALL-LABEL: ret_float_0x0:
|
||||
|
||||
; NO-MTHC1-DAG: mtc1 $zero, $f0
|
||||
|
||||
; MTHC1-DAG: mtc1 $zero, $f0
|
||||
|
||||
; DMTC-DAG: dmtc1 $zero, $f0
|
||||
|
||||
; ALL-DAG: jr $ra
|
||||
ret float 0x0000000000000000
|
||||
}
|
||||
|
||||
define float @ret_float_0x3() {
|
||||
; ALL-LABEL: ret_float_0x3:
|
||||
|
||||
; Use a constant pool
|
||||
; O32-DAG: lwc1 $f0, %lo($CPI
|
||||
; N64-DAG: lwc1 $f0, %got_ofst($CPI
|
||||
|
||||
; ALL-DAG: jr $ra
|
||||
|
||||
; float constants are written as double constants
|
||||
ret float 0x36b8000000000000
|
||||
}
|
||||
|
||||
define double @ret_double_0x0() {
|
||||
; ALL-LABEL: ret_double_0x0:
|
||||
|
||||
; NO-MTHC1-DAG: mtc1 $zero, $f0
|
||||
; NO-MTHC1-DAG: mtc1 $zero, $f1
|
||||
|
||||
; MTHC1-DAG: mtc1 $zero, $f0
|
||||
; MTHC1-DAG: mthc1 $zero, $f0
|
||||
|
||||
; DMTC-DAG: dmtc1 $zero, $f0
|
||||
|
||||
; ALL-DAG: jr $ra
|
||||
ret double 0x0000000000000000
|
||||
}
|
||||
|
||||
define double @ret_double_0x3() {
|
||||
; ALL-LABEL: ret_double_0x3:
|
||||
|
||||
; Use a constant pool
|
||||
; O32-DAG: ldc1 $f0, %lo($CPI
|
||||
; N64-DAG: ldc1 $f0, %got_ofst($CPI
|
||||
|
||||
; ALL-DAG: jr $ra
|
||||
ret double 0x0000000000000003
|
||||
}
|
Loading…
Reference in New Issue
Block a user