[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:
Daniel Sanders 2014-07-04 15:16:14 +00:00
parent ada0f6a93e
commit 8ce13cfc08
3 changed files with 353 additions and 0 deletions

View 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
}

View 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
}

View 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
}